From 2b8ddf8b681744138c1ab871cc43ed414a954950 Mon Sep 17 00:00:00 2001 From: Jonatha Cardoso Date: Wed, 8 Jun 2022 09:07:10 -0300 Subject: [PATCH 1/7] Release: 3.1.2 --- config/bootstrap_admin/filter.html | 9 - config/initial_data/auth_group.json | 85 -- config/initial_data/auth_permission.json | 772 ++++++++---------- config/initial_data/django_content_type.sql | 137 ++-- docker/Dockerfile | 1 - docker/docker-compose.yml | 5 +- docker/start.sh | 3 - docs/deploy.rst | 20 +- docs/docker.rst | 30 +- docs/instalacao.rst | 16 +- requirements/dev-requirements.txt | 8 +- requirements/requirements.txt | 10 +- saap/cerimonial/forms.py | 246 +++++- .../migrations/0091_auto_20220531_1341.py | 44 + .../migrations/0092_auto_20220601_0925.py | 22 + saap/cerimonial/models.py | 69 +- saap/cerimonial/reports.py | 336 +++++++- saap/cerimonial/urls.py | 33 +- saap/cerimonial/utils.py | 198 ++++- saap/cerimonial/views.py | 114 ++- saap/core/admin.py | 31 + saap/core/apps.py | 3 + saap/core/migrations/0033_auditlog.py | 33 + saap/core/models.py | 40 + saap/core/receivers.py | 78 ++ saap/settings.py | 12 +- saap/static/styles/app.css | 20 + saap/templates/base.html | 13 +- saap/templates/cerimonial/aniversarios.html | 20 + .../{agenda.html => calendario.html} | 6 +- saap/templates/cerimonial/evento.html | 37 - .../cerimonial/filter_contatoemail.html | 77 ++ .../templates/cerimonial/filter_contatos.html | 9 +- saap/templates/cerimonial/filter_evento.html | 102 +++ .../filter_impressoenderecamento_contato.html | 3 + saap/templates/cerimonial/layouts.yaml | 7 + saap/templates/home/home_page.html | 14 - saap/templates/relatorios.html | 11 +- saap/urls.py | 4 +- 39 files changed, 1792 insertions(+), 886 deletions(-) delete mode 100644 config/bootstrap_admin/filter.html create mode 100644 saap/cerimonial/migrations/0091_auto_20220531_1341.py create mode 100644 saap/cerimonial/migrations/0092_auto_20220601_0925.py create mode 100644 saap/core/migrations/0033_auditlog.py create mode 100644 saap/core/receivers.py create mode 100644 saap/templates/cerimonial/aniversarios.html rename saap/templates/cerimonial/{agenda.html => calendario.html} (69%) delete mode 100644 saap/templates/cerimonial/evento.html create mode 100644 saap/templates/cerimonial/filter_contatoemail.html create mode 100644 saap/templates/cerimonial/filter_evento.html delete mode 100644 saap/templates/home/home_page.html diff --git a/config/bootstrap_admin/filter.html b/config/bootstrap_admin/filter.html deleted file mode 100644 index 5174443..0000000 --- a/config/bootstrap_admin/filter.html +++ /dev/null @@ -1,9 +0,0 @@ -{% load i18n %} -

{% blocktrans with filter_title=title %} By {{ filter_title }} {% endblocktrans %}

- diff --git a/config/initial_data/auth_group.json b/config/initial_data/auth_group.json index b38b117..db47e45 100644 --- a/config/initial_data/auth_group.json +++ b/config/initial_data/auth_group.json @@ -442,91 +442,6 @@ 254, 256, 255, - 69, - 70, - 71, - 72, - 73, - 94, - 95, - 96, - 98, - 97, - 79, - 80, - 81, - 82, - 83, - 89, - 90, - 91, - 93, - 92, - 119, - 120, - 121, - 122, - 123, - 114, - 115, - 116, - 117, - 118, - 104, - 105, - 106, - 108, - 107, - 44, - 45, - 46, - 47, - 48, - 49, - 50, - 51, - 53, - 52, - 74, - 75, - 76, - 78, - 77, - 59, - 60, - 61, - 63, - 62, - 64, - 65, - 66, - 67, - 68, - 84, - 85, - 86, - 87, - 88, - 54, - 55, - 56, - 58, - 57, - 99, - 100, - 101, - 102, - 103, - 109, - 110, - 111, - 113, - 112, - 31, - 32, - 33, - 37, - 39, 34, 38, 41, diff --git a/config/initial_data/auth_permission.json b/config/initial_data/auth_permission.json index 4ee159f..b1e99c9 100644 --- a/config/initial_data/auth_permission.json +++ b/config/initial_data/auth_permission.json @@ -3,7 +3,7 @@ "model": "auth.permission", "pk": 1, "fields": { - "name": "Can add log entry", + "name": "Exclusão de log entry", "content_type": 1, "codename": "add_logentry" } @@ -12,7 +12,7 @@ "model": "auth.permission", "pk": 2, "fields": { - "name": "Can change log entry", + "name": "Exclusão de log entry", "content_type": 1, "codename": "change_logentry" } @@ -21,7 +21,7 @@ "model": "auth.permission", "pk": 3, "fields": { - "name": "Can delete log entry", + "name": "Exclusão de log entry", "content_type": 1, "codename": "delete_logentry" } @@ -30,7 +30,7 @@ "model": "auth.permission", "pk": 4, "fields": { - "name": "Can add permission", + "name": "Exclusão de permission", "content_type": 2, "codename": "add_permission" } @@ -39,7 +39,7 @@ "model": "auth.permission", "pk": 5, "fields": { - "name": "Can change permission", + "name": "Exclusão de permission", "content_type": 2, "codename": "change_permission" } @@ -48,7 +48,7 @@ "model": "auth.permission", "pk": 6, "fields": { - "name": "Can delete permission", + "name": "Exclusão de permission", "content_type": 2, "codename": "delete_permission" } @@ -57,7 +57,7 @@ "model": "auth.permission", "pk": 7, "fields": { - "name": "Can add group", + "name": "Exclusão de group", "content_type": 3, "codename": "add_group" } @@ -66,7 +66,7 @@ "model": "auth.permission", "pk": 8, "fields": { - "name": "Can change group", + "name": "Exclusão de group", "content_type": 3, "codename": "change_group" } @@ -75,7 +75,7 @@ "model": "auth.permission", "pk": 9, "fields": { - "name": "Can delete group", + "name": "Exclusão de group", "content_type": 3, "codename": "delete_group" } @@ -84,7 +84,7 @@ "model": "auth.permission", "pk": 10, "fields": { - "name": "Can add content type", + "name": "Exclusão de content type", "content_type": 4, "codename": "add_contenttype" } @@ -93,7 +93,7 @@ "model": "auth.permission", "pk": 11, "fields": { - "name": "Can change content type", + "name": "Exclusão de content type", "content_type": 4, "codename": "change_contenttype" } @@ -102,7 +102,7 @@ "model": "auth.permission", "pk": 12, "fields": { - "name": "Can delete content type", + "name": "Exclusão de content type", "content_type": 4, "codename": "delete_contenttype" } @@ -111,7 +111,7 @@ "model": "auth.permission", "pk": 13, "fields": { - "name": "Can add session", + "name": "Exclusão de session", "content_type": 5, "codename": "add_session" } @@ -120,7 +120,7 @@ "model": "auth.permission", "pk": 14, "fields": { - "name": "Can change session", + "name": "Exclusão de session", "content_type": 5, "codename": "change_session" } @@ -129,7 +129,7 @@ "model": "auth.permission", "pk": 15, "fields": { - "name": "Can delete session", + "name": "Exclusão de session", "content_type": 5, "codename": "delete_session" } @@ -138,7 +138,7 @@ "model": "auth.permission", "pk": 16, "fields": { - "name": "Can add source", + "name": "Exclusão de source", "content_type": 6, "codename": "add_source" } @@ -147,7 +147,7 @@ "model": "auth.permission", "pk": 17, "fields": { - "name": "Can change source", + "name": "Exclusão de source", "content_type": 6, "codename": "change_source" } @@ -156,7 +156,7 @@ "model": "auth.permission", "pk": 18, "fields": { - "name": "Can delete source", + "name": "Exclusão de source", "content_type": 6, "codename": "delete_source" } @@ -165,7 +165,7 @@ "model": "auth.permission", "pk": 19, "fields": { - "name": "Can add thumbnail", + "name": "Exclusão de thumbnail", "content_type": 7, "codename": "add_thumbnail" } @@ -174,7 +174,7 @@ "model": "auth.permission", "pk": 20, "fields": { - "name": "Can change thumbnail", + "name": "Exclusão de thumbnail", "content_type": 7, "codename": "change_thumbnail" } @@ -183,7 +183,7 @@ "model": "auth.permission", "pk": 21, "fields": { - "name": "Can delete thumbnail", + "name": "Exclusão de thumbnail", "content_type": 7, "codename": "delete_thumbnail" } @@ -192,7 +192,7 @@ "model": "auth.permission", "pk": 22, "fields": { - "name": "Can add thumbnail dimensions", + "name": "Exclusão de thumbnail dimensions", "content_type": 8, "codename": "add_thumbnaildimensions" } @@ -201,7 +201,7 @@ "model": "auth.permission", "pk": 23, "fields": { - "name": "Can change thumbnail dimensions", + "name": "Exclusão de thumbnail dimensions", "content_type": 8, "codename": "change_thumbnaildimensions" } @@ -210,7 +210,7 @@ "model": "auth.permission", "pk": 24, "fields": { - "name": "Can delete thumbnail dimensions", + "name": "Exclusão de thumbnail dimensions", "content_type": 8, "codename": "delete_thumbnaildimensions" } @@ -219,7 +219,7 @@ "model": "auth.permission", "pk": 25, "fields": { - "name": "Can add Tag", + "name": "Exclusão de Tag", "content_type": 9, "codename": "add_tag" } @@ -228,7 +228,7 @@ "model": "auth.permission", "pk": 26, "fields": { - "name": "Can change Tag", + "name": "Exclusão de Tag", "content_type": 9, "codename": "change_tag" } @@ -237,7 +237,7 @@ "model": "auth.permission", "pk": 27, "fields": { - "name": "Can delete Tag", + "name": "Exclusão de Tag", "content_type": 9, "codename": "delete_tag" } @@ -246,7 +246,7 @@ "model": "auth.permission", "pk": 28, "fields": { - "name": "Can add Tagged Item", + "name": "Exclusão de Tagged Item", "content_type": 10, "codename": "add_taggeditem" } @@ -255,7 +255,7 @@ "model": "auth.permission", "pk": 29, "fields": { - "name": "Can change Tagged Item", + "name": "Exclusão de Tagged Item", "content_type": 10, "codename": "change_taggeditem" } @@ -264,7 +264,7 @@ "model": "auth.permission", "pk": 30, "fields": { - "name": "Can delete Tagged Item", + "name": "Exclusão de Tagged Item", "content_type": 10, "codename": "delete_taggeditem" } @@ -273,7 +273,7 @@ "model": "auth.permission", "pk": 31, "fields": { - "name": "Can add user", + "name": "Exclusão de user", "content_type": 11, "codename": "add_user" } @@ -282,7 +282,7 @@ "model": "auth.permission", "pk": 32, "fields": { - "name": "Can change user", + "name": "Exclusão de user", "content_type": 11, "codename": "change_user" } @@ -291,7 +291,7 @@ "model": "auth.permission", "pk": 33, "fields": { - "name": "Can delete user", + "name": "Exclusão de user", "content_type": 11, "codename": "delete_user" } @@ -300,7 +300,7 @@ "model": "auth.permission", "pk": 34, "fields": { - "name": "Mostrar Menu de \u00c1reas de Trabalho", + "name": "Exibição de Menu de \u00c1reas de Trabalho", "content_type": 11, "codename": "menu_area_trabalho" } @@ -309,7 +309,7 @@ "model": "auth.permission", "pk": 35, "fields": { - "name": "Mostrar Menu de Impressos de Endere\u00e7amento", + "name": "Exibição de Menu de Impressos de Endere\u00e7amento", "content_type": 11, "codename": "menu_impresso_enderecamento" } @@ -318,7 +318,7 @@ "model": "auth.permission", "pk": 36, "fields": { - "name": "Mostrar Menu de Tabelas Auxiliares", + "name": "Exibição de Menu de Tabelas Auxiliares", "content_type": 11, "codename": "menu_tabelas_auxiliares" } @@ -336,7 +336,7 @@ "model": "auth.permission", "pk": 38, "fields": { - "name": "Mostrar Menu de Cadastro de Contatos", + "name": "Exibição de Menu de Cadastro de Contatos", "content_type": 11, "codename": "menu_contatos" } @@ -354,7 +354,7 @@ "model": "auth.permission", "pk": 40, "fields": { - "name": "Mostrar Menu de Relat\u00f3rios", + "name": "Exibição de Menu de Relat\u00f3rios", "content_type": 11, "codename": "menu_relatorios" } @@ -363,7 +363,7 @@ "model": "auth.permission", "pk": 41, "fields": { - "name": "Mostrar Menu Dados Auxiliares", + "name": "Exibição de Menu Dados Auxiliares", "content_type": 11, "codename": "menu_dados_auxiliares" } @@ -372,7 +372,7 @@ "model": "auth.permission", "pk": 42, "fields": { - "name": "Mostrar Menu de Cadastro de Grupos de Contatos", + "name": "Exibição de Menu de Cadastro de Grupos de Contatos", "content_type": 11, "codename": "menu_grupocontatos" } @@ -381,7 +381,7 @@ "model": "auth.permission", "pk": 43, "fields": { - "name": "Mostrar Menu de Cadastro de Processos", + "name": "Exibição de Menu de Cadastro de Processos", "content_type": 11, "codename": "menu_processos" } @@ -390,7 +390,7 @@ "model": "auth.permission", "pk": 44, "fields": { - "name": "Can add Munic\u00edpio", + "name": "Exclusão de Munic\u00edpio", "content_type": 12, "codename": "add_municipio" } @@ -399,7 +399,7 @@ "model": "auth.permission", "pk": 45, "fields": { - "name": "Can change Munic\u00edpio", + "name": "Exclusão de Munic\u00edpio", "content_type": 12, "codename": "change_municipio" } @@ -408,7 +408,7 @@ "model": "auth.permission", "pk": 46, "fields": { - "name": "Can delete Munic\u00edpio", + "name": "Exclusão de Munic\u00edpio", "content_type": 12, "codename": "delete_municipio" } @@ -435,7 +435,7 @@ "model": "auth.permission", "pk": 49, "fields": { - "name": "Can add N\u00edvel Instru\u00e7\u00e3o", + "name": "Exclusão de N\u00edvel Instru\u00e7\u00e3o", "content_type": 13, "codename": "add_nivelinstrucao" } @@ -444,7 +444,7 @@ "model": "auth.permission", "pk": 50, "fields": { - "name": "Can change N\u00edvel Instru\u00e7\u00e3o", + "name": "Exclusão de N\u00edvel Instru\u00e7\u00e3o", "content_type": 13, "codename": "change_nivelinstrucao" } @@ -453,7 +453,7 @@ "model": "auth.permission", "pk": 51, "fields": { - "name": "Can delete N\u00edvel Instru\u00e7\u00e3o", + "name": "Exclusão de N\u00edvel Instru\u00e7\u00e3o", "content_type": 13, "codename": "delete_nivelinstrucao" } @@ -480,7 +480,7 @@ "model": "auth.permission", "pk": 54, "fields": { - "name": "Can add Tipo Situa\u00e7\u00e3o Militar", + "name": "Exclusão de Tipo Situa\u00e7\u00e3o Militar", "content_type": 14, "codename": "add_situacaomilitar" } @@ -489,7 +489,7 @@ "model": "auth.permission", "pk": 55, "fields": { - "name": "Can change Tipo Situa\u00e7\u00e3o Militar", + "name": "Exclusão de Tipo Situa\u00e7\u00e3o Militar", "content_type": 14, "codename": "change_situacaomilitar" } @@ -498,7 +498,7 @@ "model": "auth.permission", "pk": 56, "fields": { - "name": "Can delete Tipo Situa\u00e7\u00e3o Militar", + "name": "Exclusão de Tipo Situa\u00e7\u00e3o Militar", "content_type": 14, "codename": "delete_situacaomilitar" } @@ -525,7 +525,7 @@ "model": "auth.permission", "pk": 59, "fields": { - "name": "Can add Parlamentar", + "name": "Exclusão de Parlamentar", "content_type": 15, "codename": "add_parlamentar" } @@ -534,7 +534,7 @@ "model": "auth.permission", "pk": 60, "fields": { - "name": "Can change Parlamentar", + "name": "Exclusão de Parlamentar", "content_type": 15, "codename": "change_parlamentar" } @@ -543,7 +543,7 @@ "model": "auth.permission", "pk": 61, "fields": { - "name": "Can delete Parlamentar", + "name": "Exclusão de Parlamentar", "content_type": 15, "codename": "delete_parlamentar" } @@ -570,7 +570,7 @@ "model": "auth.permission", "pk": 64, "fields": { - "name": "Can add Partido", + "name": "Exclusão de Partido", "content_type": 16, "codename": "add_partido" } @@ -579,7 +579,7 @@ "model": "auth.permission", "pk": 65, "fields": { - "name": "Can change Partido", + "name": "Exclusão de Partido", "content_type": 16, "codename": "change_partido" } @@ -588,7 +588,7 @@ "model": "auth.permission", "pk": 66, "fields": { - "name": "Can delete Partido", + "name": "Exclusão de Partido", "content_type": 16, "codename": "delete_partido" } @@ -615,7 +615,7 @@ "model": "auth.permission", "pk": 69, "fields": { - "name": "Can add \u00c1rea de Trabalho", + "name": "Exclusão de \u00c1rea de Trabalho", "content_type": 17, "codename": "add_areatrabalho" } @@ -624,7 +624,7 @@ "model": "auth.permission", "pk": 70, "fields": { - "name": "Can change \u00c1rea de Trabalho", + "name": "Exclusão de \u00c1rea de Trabalho", "content_type": 17, "codename": "change_areatrabalho" } @@ -633,7 +633,7 @@ "model": "auth.permission", "pk": 71, "fields": { - "name": "Can delete \u00c1rea de Trabalho", + "name": "Exclusão de \u00c1rea de Trabalho", "content_type": 17, "codename": "delete_areatrabalho" } @@ -660,7 +660,7 @@ "model": "auth.permission", "pk": 74, "fields": { - "name": "Can add Operador", + "name": "Exclusão de Operador", "content_type": 18, "codename": "add_operadorareatrabalho" } @@ -669,7 +669,7 @@ "model": "auth.permission", "pk": 75, "fields": { - "name": "Can change Operador", + "name": "Exclusão de Operador", "content_type": 18, "codename": "change_operadorareatrabalho" } @@ -678,7 +678,7 @@ "model": "auth.permission", "pk": 76, "fields": { - "name": "Can delete Operador", + "name": "Exclusão de Operador", "content_type": 18, "codename": "delete_operadorareatrabalho" } @@ -705,7 +705,7 @@ "model": "auth.permission", "pk": 79, "fields": { - "name": "Can add CEP", + "name": "Exclusão de CEP", "content_type": 19, "codename": "add_cep" } @@ -714,7 +714,7 @@ "model": "auth.permission", "pk": 80, "fields": { - "name": "Can change CEP", + "name": "Exclusão de CEP", "content_type": 19, "codename": "change_cep" } @@ -723,7 +723,7 @@ "model": "auth.permission", "pk": 81, "fields": { - "name": "Can delete CEP", + "name": "Exclusão de CEP", "content_type": 19, "codename": "delete_cep" } @@ -750,7 +750,7 @@ "model": "auth.permission", "pk": 84, "fields": { - "name": "Can add Regi\u00e3o Municipal", + "name": "Exclusão de Regi\u00e3o Municipal", "content_type": 20, "codename": "add_regiaomunicipal" } @@ -759,7 +759,7 @@ "model": "auth.permission", "pk": 85, "fields": { - "name": "Can change Regi\u00e3o Municipal", + "name": "Exclusão de Regi\u00e3o Municipal", "content_type": 20, "codename": "change_regiaomunicipal" } @@ -768,7 +768,7 @@ "model": "auth.permission", "pk": 86, "fields": { - "name": "Can delete Regi\u00e3o Municipal", + "name": "Exclusão de Regi\u00e3o Municipal", "content_type": 20, "codename": "delete_regiaomunicipal" } @@ -795,7 +795,7 @@ "model": "auth.permission", "pk": 89, "fields": { - "name": "Can add Distrito", + "name": "Exclusão de Distrito", "content_type": 21, "codename": "add_distrito" } @@ -804,7 +804,7 @@ "model": "auth.permission", "pk": 90, "fields": { - "name": "Can change Distrito", + "name": "Exclusão de Distrito", "content_type": 21, "codename": "change_distrito" } @@ -813,7 +813,7 @@ "model": "auth.permission", "pk": 91, "fields": { - "name": "Can delete Distrito", + "name": "Exclusão de Distrito", "content_type": 21, "codename": "delete_distrito" } @@ -840,7 +840,7 @@ "model": "auth.permission", "pk": 94, "fields": { - "name": "Can add Bairro", + "name": "Exclusão de Bairro", "content_type": 22, "codename": "add_bairro" } @@ -849,7 +849,7 @@ "model": "auth.permission", "pk": 95, "fields": { - "name": "Can change Bairro", + "name": "Exclusão de Bairro", "content_type": 22, "codename": "change_bairro" } @@ -858,7 +858,7 @@ "model": "auth.permission", "pk": 96, "fields": { - "name": "Can delete Bairro", + "name": "Exclusão de Bairro", "content_type": 22, "codename": "delete_bairro" } @@ -885,7 +885,7 @@ "model": "auth.permission", "pk": 99, "fields": { - "name": "Can add Tipo de Logradouro", + "name": "Exclusão de Tipo de Logradouro", "content_type": 23, "codename": "add_tipologradouro" } @@ -894,7 +894,7 @@ "model": "auth.permission", "pk": 100, "fields": { - "name": "Can change Tipo de Logradouro", + "name": "Exclusão de Tipo de Logradouro", "content_type": 23, "codename": "change_tipologradouro" } @@ -903,7 +903,7 @@ "model": "auth.permission", "pk": 101, "fields": { - "name": "Can delete Tipo de Logradouro", + "name": "Exclusão de Tipo de Logradouro", "content_type": 23, "codename": "delete_tipologradouro" } @@ -930,7 +930,7 @@ "model": "auth.permission", "pk": 104, "fields": { - "name": "Can add Logradouro", + "name": "Exclusão de Logradouro", "content_type": 24, "codename": "add_logradouro" } @@ -939,7 +939,7 @@ "model": "auth.permission", "pk": 105, "fields": { - "name": "Can change Logradouro", + "name": "Exclusão de Logradouro", "content_type": 24, "codename": "change_logradouro" } @@ -948,7 +948,7 @@ "model": "auth.permission", "pk": 106, "fields": { - "name": "Can delete Logradouro", + "name": "Exclusão de Logradouro", "content_type": 24, "codename": "delete_logradouro" } @@ -975,7 +975,7 @@ "model": "auth.permission", "pk": 109, "fields": { - "name": "Can add Trecho de Logradouro", + "name": "Exclusão de Trecho de Logradouro", "content_type": 25, "codename": "add_trecho" } @@ -984,7 +984,7 @@ "model": "auth.permission", "pk": 110, "fields": { - "name": "Can change Trecho de Logradouro", + "name": "Exclusão de Trecho de Logradouro", "content_type": 25, "codename": "change_trecho" } @@ -993,7 +993,7 @@ "model": "auth.permission", "pk": 111, "fields": { - "name": "Can delete Trecho de Logradouro", + "name": "Exclusão de Trecho de Logradouro", "content_type": 25, "codename": "delete_trecho" } @@ -1020,7 +1020,7 @@ "model": "auth.permission", "pk": 114, "fields": { - "name": "Can add Impresso para Endere\u00e7amento", + "name": "Exclusão de Impresso para Endere\u00e7amento", "content_type": 26, "codename": "add_impressoenderecamento" } @@ -1029,7 +1029,7 @@ "model": "auth.permission", "pk": 115, "fields": { - "name": "Can change Impresso para Endere\u00e7amento", + "name": "Exclusão de Impresso para Endere\u00e7amento", "content_type": 26, "codename": "change_impressoenderecamento" } @@ -1038,7 +1038,7 @@ "model": "auth.permission", "pk": 116, "fields": { - "name": "Can delete Impresso para Endere\u00e7amento", + "name": "Exclusão de Impresso para Endere\u00e7amento", "content_type": 26, "codename": "delete_impressoenderecamento" } @@ -1065,7 +1065,7 @@ "model": "auth.permission", "pk": 119, "fields": { - "name": "Can add Filia\u00e7\u00e3o", + "name": "Exclusão de Filia\u00e7\u00e3o", "content_type": 27, "codename": "add_filiacao" } @@ -1074,7 +1074,7 @@ "model": "auth.permission", "pk": 120, "fields": { - "name": "Can change Filia\u00e7\u00e3o", + "name": "Exclusão de Filia\u00e7\u00e3o", "content_type": 27, "codename": "change_filiacao" } @@ -1083,7 +1083,7 @@ "model": "auth.permission", "pk": 121, "fields": { - "name": "Can delete Filia\u00e7\u00e3o", + "name": "Exclusão de Filia\u00e7\u00e3o", "content_type": 27, "codename": "delete_filiacao" } @@ -1110,7 +1110,7 @@ "model": "auth.permission", "pk": 124, "fields": { - "name": "Can add Tipo de Telefone", + "name": "Exclusão de Tipo de Telefone", "content_type": 28, "codename": "add_tipotelefone" } @@ -1119,7 +1119,7 @@ "model": "auth.permission", "pk": 125, "fields": { - "name": "Can change Tipo de Telefone", + "name": "Exclusão de Tipo de Telefone", "content_type": 28, "codename": "change_tipotelefone" } @@ -1128,7 +1128,7 @@ "model": "auth.permission", "pk": 126, "fields": { - "name": "Can delete Tipo de Telefone", + "name": "Exclusão de Tipo de Telefone", "content_type": 28, "codename": "delete_tipotelefone" } @@ -1155,7 +1155,7 @@ "model": "auth.permission", "pk": 129, "fields": { - "name": "Can add Tipo de Endere\u00e7o", + "name": "Exclusão de Tipo de Endere\u00e7o", "content_type": 29, "codename": "add_tipoendereco" } @@ -1164,7 +1164,7 @@ "model": "auth.permission", "pk": 130, "fields": { - "name": "Can change Tipo de Endere\u00e7o", + "name": "Exclusão de Tipo de Endere\u00e7o", "content_type": 29, "codename": "change_tipoendereco" } @@ -1173,7 +1173,7 @@ "model": "auth.permission", "pk": 131, "fields": { - "name": "Can delete Tipo de Endere\u00e7o", + "name": "Exclusão de Tipo de Endere\u00e7o", "content_type": 29, "codename": "delete_tipoendereco" } @@ -1200,7 +1200,7 @@ "model": "auth.permission", "pk": 134, "fields": { - "name": "Can add Tipo de Email", + "name": "Exclusão de Tipo de Email", "content_type": 30, "codename": "add_tipoemail" } @@ -1209,7 +1209,7 @@ "model": "auth.permission", "pk": 135, "fields": { - "name": "Can change Tipo de Email", + "name": "Exclusão de Tipo de Email", "content_type": 30, "codename": "change_tipoemail" } @@ -1218,7 +1218,7 @@ "model": "auth.permission", "pk": 136, "fields": { - "name": "Can delete Tipo de Email", + "name": "Exclusão de Tipo de Email", "content_type": 30, "codename": "delete_tipoemail" } @@ -1245,7 +1245,7 @@ "model": "auth.permission", "pk": 139, "fields": { - "name": "Can add Parentesco", + "name": "Exclusão de Parentesco", "content_type": 31, "codename": "add_parentesco" } @@ -1254,7 +1254,7 @@ "model": "auth.permission", "pk": 140, "fields": { - "name": "Can change Parentesco", + "name": "Exclusão de Parentesco", "content_type": 31, "codename": "change_parentesco" } @@ -1263,7 +1263,7 @@ "model": "auth.permission", "pk": 141, "fields": { - "name": "Can delete Parentesco", + "name": "Exclusão de Parentesco", "content_type": 31, "codename": "delete_parentesco" } @@ -1290,7 +1290,7 @@ "model": "auth.permission", "pk": 144, "fields": { - "name": "Can add Estado Civil", + "name": "Exclusão de Estado Civil", "content_type": 32, "codename": "add_estadocivil" } @@ -1299,7 +1299,7 @@ "model": "auth.permission", "pk": 145, "fields": { - "name": "Can change Estado Civil", + "name": "Exclusão de Estado Civil", "content_type": 32, "codename": "change_estadocivil" } @@ -1308,7 +1308,7 @@ "model": "auth.permission", "pk": 146, "fields": { - "name": "Can delete Estado Civil", + "name": "Exclusão de Estado Civil", "content_type": 32, "codename": "delete_estadocivil" } @@ -1335,7 +1335,7 @@ "model": "auth.permission", "pk": 149, "fields": { - "name": "Can add Pronome de Tratamento", + "name": "Exclusão de Pronome de Tratamento", "content_type": 33, "codename": "add_pronometratamento" } @@ -1344,7 +1344,7 @@ "model": "auth.permission", "pk": 150, "fields": { - "name": "Can change Pronome de Tratamento", + "name": "Exclusão de Pronome de Tratamento", "content_type": 33, "codename": "change_pronometratamento" } @@ -1353,7 +1353,7 @@ "model": "auth.permission", "pk": 151, "fields": { - "name": "Can delete Pronome de Tratamento", + "name": "Exclusão de Pronome de Tratamento", "content_type": 33, "codename": "delete_pronometratamento" } @@ -1380,7 +1380,7 @@ "model": "auth.permission", "pk": 154, "fields": { - "name": "Can add Tipo de Autoridade", + "name": "Exclusão de Tipo de Autoridade", "content_type": 34, "codename": "add_tipoautoridade" } @@ -1389,7 +1389,7 @@ "model": "auth.permission", "pk": 155, "fields": { - "name": "Can change Tipo de Autoridade", + "name": "Exclusão de Tipo de Autoridade", "content_type": 34, "codename": "change_tipoautoridade" } @@ -1398,7 +1398,7 @@ "model": "auth.permission", "pk": 156, "fields": { - "name": "Can delete Tipo de Autoridade", + "name": "Exclusão de Tipo de Autoridade", "content_type": 34, "codename": "delete_tipoautoridade" } @@ -1425,7 +1425,7 @@ "model": "auth.permission", "pk": 159, "fields": { - "name": "Can add Tipo do Local de Trabalho", + "name": "Exclusão de Tipo do Local de Trabalho", "content_type": 35, "codename": "add_tipolocaltrabalho" } @@ -1434,7 +1434,7 @@ "model": "auth.permission", "pk": 160, "fields": { - "name": "Can change Tipo do Local de Trabalho", + "name": "Exclusão de Tipo do Local de Trabalho", "content_type": 35, "codename": "change_tipolocaltrabalho" } @@ -1443,7 +1443,7 @@ "model": "auth.permission", "pk": 161, "fields": { - "name": "Can delete Tipo do Local de Trabalho", + "name": "Exclusão de Tipo do Local de Trabalho", "content_type": 35, "codename": "delete_tipolocaltrabalho" } @@ -1470,7 +1470,7 @@ "model": "auth.permission", "pk": 164, "fields": { - "name": "Can add N\u00edvel de Instru\u00e7\u00e3o", + "name": "Exclusão de N\u00edvel de Instru\u00e7\u00e3o", "content_type": 36, "codename": "add_nivelinstrucao" } @@ -1479,7 +1479,7 @@ "model": "auth.permission", "pk": 165, "fields": { - "name": "Can change N\u00edvel de Instru\u00e7\u00e3o", + "name": "Exclusão de N\u00edvel de Instru\u00e7\u00e3o", "content_type": 36, "codename": "change_nivelinstrucao" } @@ -1488,7 +1488,7 @@ "model": "auth.permission", "pk": 166, "fields": { - "name": "Can delete N\u00edvel de Instru\u00e7\u00e3o", + "name": "Exclusão de N\u00edvel de Instru\u00e7\u00e3o", "content_type": 36, "codename": "delete_nivelinstrucao" } @@ -1515,7 +1515,7 @@ "model": "auth.permission", "pk": 169, "fields": { - "name": "Can add Operadora de Telefonia", + "name": "Exclusão de Operadora de Telefonia", "content_type": 37, "codename": "add_operadoratelefonia" } @@ -1524,7 +1524,7 @@ "model": "auth.permission", "pk": 170, "fields": { - "name": "Can change Operadora de Telefonia", + "name": "Exclusão de Operadora de Telefonia", "content_type": 37, "codename": "change_operadoratelefonia" } @@ -1533,7 +1533,7 @@ "model": "auth.permission", "pk": 171, "fields": { - "name": "Can delete Operadora de Telefonia", + "name": "Exclusão de Operadora de Telefonia", "content_type": 37, "codename": "delete_operadoratelefonia" } @@ -1560,7 +1560,7 @@ "model": "auth.permission", "pk": 174, "fields": { - "name": "Can add Contato", + "name": "Exclusão de Contato", "content_type": 38, "codename": "add_contato" } @@ -1569,7 +1569,7 @@ "model": "auth.permission", "pk": 175, "fields": { - "name": "Can change Contato", + "name": "Exclusão de Contato", "content_type": 38, "codename": "change_contato" } @@ -1578,7 +1578,7 @@ "model": "auth.permission", "pk": 176, "fields": { - "name": "Can delete Contato", + "name": "Exclusão de Contato", "content_type": 38, "codename": "delete_contato" } @@ -1632,7 +1632,7 @@ "model": "auth.permission", "pk": 182, "fields": { - "name": "Can add perfil", + "name": "Exclusão de perfil", "content_type": 39, "codename": "add_perfil" } @@ -1641,7 +1641,7 @@ "model": "auth.permission", "pk": 183, "fields": { - "name": "Can change perfil", + "name": "Exclusão de perfil", "content_type": 39, "codename": "change_perfil" } @@ -1650,7 +1650,7 @@ "model": "auth.permission", "pk": 184, "fields": { - "name": "Can delete perfil", + "name": "Exclusão de perfil", "content_type": 39, "codename": "delete_perfil" } @@ -1677,7 +1677,7 @@ "model": "auth.permission", "pk": 187, "fields": { - "name": "Can add Telefone", + "name": "Exclusão de Telefone", "content_type": 40, "codename": "add_telefone" } @@ -1686,7 +1686,7 @@ "model": "auth.permission", "pk": 188, "fields": { - "name": "Can change Telefone", + "name": "Exclusão de Telefone", "content_type": 40, "codename": "change_telefone" } @@ -1695,7 +1695,7 @@ "model": "auth.permission", "pk": 189, "fields": { - "name": "Can delete Telefone", + "name": "Exclusão de Telefone", "content_type": 40, "codename": "delete_telefone" } @@ -1722,7 +1722,7 @@ "model": "auth.permission", "pk": 192, "fields": { - "name": "Can add Telefone do Perfil", + "name": "Exclusão de Telefone do Perfil", "content_type": 41, "codename": "add_telefoneperfil" } @@ -1731,7 +1731,7 @@ "model": "auth.permission", "pk": 193, "fields": { - "name": "Can change Telefone do Perfil", + "name": "Exclusão de Telefone do Perfil", "content_type": 41, "codename": "change_telefoneperfil" } @@ -1740,7 +1740,7 @@ "model": "auth.permission", "pk": 194, "fields": { - "name": "Can delete Telefone do Perfil", + "name": "Exclusão de Telefone do Perfil", "content_type": 41, "codename": "delete_telefoneperfil" } @@ -1767,7 +1767,7 @@ "model": "auth.permission", "pk": 197, "fields": { - "name": "Can add Email", + "name": "Exclusão de Email", "content_type": 42, "codename": "add_email" } @@ -1776,7 +1776,7 @@ "model": "auth.permission", "pk": 198, "fields": { - "name": "Can change Email", + "name": "Exclusão de Email", "content_type": 42, "codename": "change_email" } @@ -1785,7 +1785,7 @@ "model": "auth.permission", "pk": 199, "fields": { - "name": "Can delete Email", + "name": "Exclusão de Email", "content_type": 42, "codename": "delete_email" } @@ -1812,7 +1812,7 @@ "model": "auth.permission", "pk": 202, "fields": { - "name": "Can add Email do Perfil", + "name": "Exclusão de Email do Perfil", "content_type": 43, "codename": "add_emailperfil" } @@ -1821,7 +1821,7 @@ "model": "auth.permission", "pk": 203, "fields": { - "name": "Can change Email do Perfil", + "name": "Exclusão de Email do Perfil", "content_type": 43, "codename": "change_emailperfil" } @@ -1830,7 +1830,7 @@ "model": "auth.permission", "pk": 204, "fields": { - "name": "Can delete Email do Perfil", + "name": "Exclusão de Email do Perfil", "content_type": 43, "codename": "delete_emailperfil" } @@ -1857,7 +1857,7 @@ "model": "auth.permission", "pk": 207, "fields": { - "name": "Can add Dependente", + "name": "Exclusão de Dependente", "content_type": 44, "codename": "add_dependente" } @@ -1866,7 +1866,7 @@ "model": "auth.permission", "pk": 208, "fields": { - "name": "Can change Dependente", + "name": "Exclusão de Dependente", "content_type": 44, "codename": "change_dependente" } @@ -1875,7 +1875,7 @@ "model": "auth.permission", "pk": 209, "fields": { - "name": "Can delete Dependente", + "name": "Exclusão de Dependente", "content_type": 44, "codename": "delete_dependente" } @@ -1902,7 +1902,7 @@ "model": "auth.permission", "pk": 212, "fields": { - "name": "Can add Dependente do Perfil", + "name": "Exclusão de Dependente do Perfil", "content_type": 45, "codename": "add_dependenteperfil" } @@ -1911,7 +1911,7 @@ "model": "auth.permission", "pk": 213, "fields": { - "name": "Can change Dependente do Perfil", + "name": "Exclusão de Dependente do Perfil", "content_type": 45, "codename": "change_dependenteperfil" } @@ -1920,7 +1920,7 @@ "model": "auth.permission", "pk": 214, "fields": { - "name": "Can delete Dependente do Perfil", + "name": "Exclusão de Dependente do Perfil", "content_type": 45, "codename": "delete_dependenteperfil" } @@ -1947,7 +1947,7 @@ "model": "auth.permission", "pk": 217, "fields": { - "name": "Can add Local de Trabalho", + "name": "Exclusão de Local de Trabalho", "content_type": 46, "codename": "add_localtrabalho" } @@ -1956,7 +1956,7 @@ "model": "auth.permission", "pk": 218, "fields": { - "name": "Can change Local de Trabalho", + "name": "Exclusão de Local de Trabalho", "content_type": 46, "codename": "change_localtrabalho" } @@ -1965,7 +1965,7 @@ "model": "auth.permission", "pk": 219, "fields": { - "name": "Can delete Local de Trabalho", + "name": "Exclusão de Local de Trabalho", "content_type": 46, "codename": "delete_localtrabalho" } @@ -1992,7 +1992,7 @@ "model": "auth.permission", "pk": 222, "fields": { - "name": "Can add Local de Trabalho do Perfil", + "name": "Exclusão de Local de Trabalho do Perfil", "content_type": 47, "codename": "add_localtrabalhoperfil" } @@ -2001,7 +2001,7 @@ "model": "auth.permission", "pk": 223, "fields": { - "name": "Can change Local de Trabalho do Perfil", + "name": "Exclusão de Local de Trabalho do Perfil", "content_type": 47, "codename": "change_localtrabalhoperfil" } @@ -2010,7 +2010,7 @@ "model": "auth.permission", "pk": 224, "fields": { - "name": "Can delete Local de Trabalho do Perfil", + "name": "Exclusão de Local de Trabalho do Perfil", "content_type": 47, "codename": "delete_localtrabalhoperfil" } @@ -2037,7 +2037,7 @@ "model": "auth.permission", "pk": 227, "fields": { - "name": "Can add Endere\u00e7o", + "name": "Exclusão de Endere\u00e7o", "content_type": 48, "codename": "add_endereco" } @@ -2046,7 +2046,7 @@ "model": "auth.permission", "pk": 228, "fields": { - "name": "Can change Endere\u00e7o", + "name": "Exclusão de Endere\u00e7o", "content_type": 48, "codename": "change_endereco" } @@ -2055,7 +2055,7 @@ "model": "auth.permission", "pk": 229, "fields": { - "name": "Can delete Endere\u00e7o", + "name": "Exclusão de Endere\u00e7o", "content_type": 48, "codename": "delete_endereco" } @@ -2082,7 +2082,7 @@ "model": "auth.permission", "pk": 232, "fields": { - "name": "Can add Endere\u00e7o do Perfil", + "name": "Exclusão de Endere\u00e7o do Perfil", "content_type": 49, "codename": "add_enderecoperfil" } @@ -2091,7 +2091,7 @@ "model": "auth.permission", "pk": 233, "fields": { - "name": "Can change Endere\u00e7o do Perfil", + "name": "Exclusão de Endere\u00e7o do Perfil", "content_type": 49, "codename": "change_enderecoperfil" } @@ -2100,7 +2100,7 @@ "model": "auth.permission", "pk": 234, "fields": { - "name": "Can delete Endere\u00e7o do Perfil", + "name": "Exclusão de Endere\u00e7o do Perfil", "content_type": 49, "codename": "delete_enderecoperfil" } @@ -2127,7 +2127,7 @@ "model": "auth.permission", "pk": 237, "fields": { - "name": "Can add Filia\u00e7\u00e3o Partid\u00e1ria", + "name": "Exclusão de Filia\u00e7\u00e3o Partid\u00e1ria", "content_type": 50, "codename": "add_filiacaopartidaria" } @@ -2136,7 +2136,7 @@ "model": "auth.permission", "pk": 238, "fields": { - "name": "Can change Filia\u00e7\u00e3o Partid\u00e1ria", + "name": "Exclusão de Filia\u00e7\u00e3o Partid\u00e1ria", "content_type": 50, "codename": "change_filiacaopartidaria" } @@ -2145,7 +2145,7 @@ "model": "auth.permission", "pk": 239, "fields": { - "name": "Can delete Filia\u00e7\u00e3o Partid\u00e1ria", + "name": "Exclusão de Filia\u00e7\u00e3o Partid\u00e1ria", "content_type": 50, "codename": "delete_filiacaopartidaria" } @@ -2172,7 +2172,7 @@ "model": "auth.permission", "pk": 242, "fields": { - "name": "Can add Status de Processo", + "name": "Exclusão de Status de Processo", "content_type": 51, "codename": "add_statusprocesso" } @@ -2181,7 +2181,7 @@ "model": "auth.permission", "pk": 243, "fields": { - "name": "Can change Status de Processo", + "name": "Exclusão de Status de Processo", "content_type": 51, "codename": "change_statusprocesso" } @@ -2190,7 +2190,7 @@ "model": "auth.permission", "pk": 244, "fields": { - "name": "Can delete Status de Processo", + "name": "Exclusão de Status de Processo", "content_type": 51, "codename": "delete_statusprocesso" } @@ -2217,7 +2217,7 @@ "model": "auth.permission", "pk": 247, "fields": { - "name": "Can add Classificacao de Processo", + "name": "Exclusão de Classificacao de Processo", "content_type": 52, "codename": "add_classificacaoprocesso" } @@ -2226,7 +2226,7 @@ "model": "auth.permission", "pk": 248, "fields": { - "name": "Can change Classificacao de Processo", + "name": "Exclusão de Classificacao de Processo", "content_type": 52, "codename": "change_classificacaoprocesso" } @@ -2235,7 +2235,7 @@ "model": "auth.permission", "pk": 249, "fields": { - "name": "Can delete Classificacao de Processo", + "name": "Exclusão de Classificacao de Processo", "content_type": 52, "codename": "delete_classificacaoprocesso" } @@ -2262,7 +2262,7 @@ "model": "auth.permission", "pk": 252, "fields": { - "name": "Can add T\u00f3pico de Processo", + "name": "Exclusão de T\u00f3pico de Processo", "content_type": 53, "codename": "add_topicoprocesso" } @@ -2271,7 +2271,7 @@ "model": "auth.permission", "pk": 253, "fields": { - "name": "Can change T\u00f3pico de Processo", + "name": "Exclusão de T\u00f3pico de Processo", "content_type": 53, "codename": "change_topicoprocesso" } @@ -2280,7 +2280,7 @@ "model": "auth.permission", "pk": 254, "fields": { - "name": "Can delete T\u00f3pico de Processo", + "name": "Exclusão de T\u00f3pico de Processo", "content_type": 53, "codename": "delete_topicoprocesso" } @@ -2307,7 +2307,7 @@ "model": "auth.permission", "pk": 257, "fields": { - "name": "Can add Assunto de Processo", + "name": "Exclusão de Assunto de Processo", "content_type": 54, "codename": "add_assuntoprocesso" } @@ -2316,7 +2316,7 @@ "model": "auth.permission", "pk": 258, "fields": { - "name": "Can change Assunto de Processo", + "name": "Exclusão de Assunto de Processo", "content_type": 54, "codename": "change_assuntoprocesso" } @@ -2325,7 +2325,7 @@ "model": "auth.permission", "pk": 259, "fields": { - "name": "Can delete Assunto de Processo", + "name": "Exclusão de Assunto de Processo", "content_type": 54, "codename": "delete_assuntoprocesso" } @@ -2352,7 +2352,7 @@ "model": "auth.permission", "pk": 262, "fields": { - "name": "Can add Processo", + "name": "Exclusão de Processo", "content_type": 55, "codename": "add_processo" } @@ -2361,7 +2361,7 @@ "model": "auth.permission", "pk": 263, "fields": { - "name": "Can change Processo", + "name": "Exclusão de Processo", "content_type": 55, "codename": "change_processo" } @@ -2370,7 +2370,7 @@ "model": "auth.permission", "pk": 264, "fields": { - "name": "Can delete Processo", + "name": "Exclusão de Processo", "content_type": 55, "codename": "delete_processo" } @@ -2397,7 +2397,7 @@ "model": "auth.permission", "pk": 267, "fields": { - "name": "Can add Processo", + "name": "Exclusão de Processo", "content_type": 56, "codename": "add_processocontato" } @@ -2406,7 +2406,7 @@ "model": "auth.permission", "pk": 268, "fields": { - "name": "Can change Processo", + "name": "Exclusão de Processo", "content_type": 56, "codename": "change_processocontato" } @@ -2415,7 +2415,7 @@ "model": "auth.permission", "pk": 269, "fields": { - "name": "Can delete Processo", + "name": "Exclusão de Processo", "content_type": 56, "codename": "delete_processocontato" } @@ -2442,7 +2442,7 @@ "model": "auth.permission", "pk": 272, "fields": { - "name": "Can add Grupo de Contatos", + "name": "Exclusão de Grupo de Contatos", "content_type": 57, "codename": "add_grupodecontatos" } @@ -2451,7 +2451,7 @@ "model": "auth.permission", "pk": 273, "fields": { - "name": "Can change Grupo de Contatos", + "name": "Exclusão de Grupo de Contatos", "content_type": 57, "codename": "change_grupodecontatos" } @@ -2460,7 +2460,7 @@ "model": "auth.permission", "pk": 274, "fields": { - "name": "Can delete Grupo de Contatos", + "name": "Exclusão de Grupo de Contatos", "content_type": 57, "codename": "delete_grupodecontatos" } @@ -2485,452 +2485,326 @@ }, { "model": "auth.permission", - "pk": 277, - "fields": { - "name": "Can add user social auth", - "content_type": 58, - "codename": "add_usersocialauth" - } -}, -{ - "model": "auth.permission", - "pk": 278, - "fields": { - "name": "Can change user social auth", - "content_type": 58, - "codename": "change_usersocialauth" - } -}, -{ - "model": "auth.permission", - "pk": 279, - "fields": { - "name": "Can delete user social auth", - "content_type": 58, - "codename": "delete_usersocialauth" - } -}, -{ - "model": "auth.permission", - "pk": 280, - "fields": { - "name": "Can add nonce", - "content_type": 59, - "codename": "add_nonce" - } -}, -{ - "model": "auth.permission", - "pk": 281, - "fields": { - "name": "Can change nonce", - "content_type": 59, - "codename": "change_nonce" - } -}, -{ - "model": "auth.permission", - "pk": 282, - "fields": { - "name": "Can delete nonce", - "content_type": 59, - "codename": "delete_nonce" - } -}, -{ - "model": "auth.permission", - "pk": 283, - "fields": { - "name": "Can add association", - "content_type": 60, - "codename": "add_association" - } -}, -{ - "model": "auth.permission", - "pk": 284, - "fields": { - "name": "Can change association", - "content_type": 60, - "codename": "change_association" - } -}, -{ - "model": "auth.permission", - "pk": 285, - "fields": { - "name": "Can delete association", - "content_type": 60, - "codename": "delete_association" - } -}, -{ - "model": "auth.permission", - "pk": 286, - "fields": { - "name": "Can add code", - "content_type": 61, - "codename": "add_code" - } -}, -{ - "model": "auth.permission", - "pk": 287, - "fields": { - "name": "Can change code", - "content_type": 61, - "codename": "change_code" - } -}, -{ - "model": "auth.permission", - "pk": 288, - "fields": { - "name": "Can delete code", - "content_type": 61, - "codename": "delete_code" - } -}, -{ - "model": "auth.permission", - "pk": 289, - "fields": { - "name": "Can add user social auth", - "content_type": 62, - "codename": "add_usersocialauth" - } -}, -{ - "model": "auth.permission", - "pk": 290, - "fields": { - "name": "Can change user social auth", - "content_type": 62, - "codename": "change_usersocialauth" - } -}, -{ - "model": "auth.permission", - "pk": 291, + "pk": 304, "fields": { - "name": "Can delete user social auth", - "content_type": 62, - "codename": "delete_usersocialauth" + "name": "Exclusão de Estado", + "content_type": 67, + "codename": "add_estado" } }, { "model": "auth.permission", - "pk": 292, + "pk": 305, "fields": { - "name": "Can add nonce", - "content_type": 63, - "codename": "add_nonce" + "name": "Exclusão de Estado", + "content_type": 67, + "codename": "change_estado" } }, { "model": "auth.permission", - "pk": 293, + "pk": 306, "fields": { - "name": "Can change nonce", - "content_type": 63, - "codename": "change_nonce" + "name": "Exclusão de Estado", + "content_type": 67, + "codename": "delete_estado" } }, { "model": "auth.permission", - "pk": 294, + "pk": 307, "fields": { - "name": "Can delete nonce", - "content_type": 63, - "codename": "delete_nonce" + "name": "Visualiza\u00e7ao da lista de Estados", + "content_type": 67, + "codename": "list_estado" } }, { "model": "auth.permission", - "pk": 295, + "pk": 308, "fields": { - "name": "Can add association", - "content_type": 64, - "codename": "add_association" + "name": "Visualiza\u00e7\u00e3o dos detalhes de Estados", + "content_type": 67, + "codename": "detail_estado" } }, { "model": "auth.permission", - "pk": 296, + "pk": 309, "fields": { - "name": "Can change association", - "content_type": 64, - "codename": "change_association" + "name": "Exclusão de country", + "content_type": 68, + "codename": "add_country" } }, { "model": "auth.permission", - "pk": 297, + "pk": 310, "fields": { - "name": "Can delete association", - "content_type": 64, - "codename": "delete_association" + "name": "Exclusão de country", + "content_type": 68, + "codename": "change_country" } }, { "model": "auth.permission", - "pk": 298, + "pk": 311, "fields": { - "name": "Can add code", - "content_type": 65, - "codename": "add_code" + "name": "Exclusão de country", + "content_type": 68, + "codename": "delete_country" } }, { "model": "auth.permission", - "pk": 299, + "pk": 312, "fields": { - "name": "Can change code", - "content_type": 65, - "codename": "change_code" + "name": "Exclusão de region/state", + "content_type": 69, + "codename": "add_region" } }, { "model": "auth.permission", - "pk": 300, + "pk": 313, "fields": { - "name": "Can delete code", - "content_type": 65, - "codename": "delete_code" + "name": "Exclusão de region/state", + "content_type": 69, + "codename": "change_region" } }, { "model": "auth.permission", - "pk": 301, + "pk": 314, "fields": { - "name": "Can add partial", - "content_type": 66, - "codename": "add_partial" + "name": "Exclusão de region/state", + "content_type": 69, + "codename": "delete_region" } }, { "model": "auth.permission", - "pk": 302, + "pk": 315, "fields": { - "name": "Can change partial", - "content_type": 66, - "codename": "change_partial" + "name": "Exclusão de city", + "content_type": 70, + "codename": "add_city" } }, { "model": "auth.permission", - "pk": 303, + "pk": 316, "fields": { - "name": "Can delete partial", - "content_type": 66, - "codename": "delete_partial" + "name": "Exclusão de city", + "content_type": 70, + "codename": "change_city" } }, { "model": "auth.permission", - "pk": 304, + "pk": 317, "fields": { - "name": "Can add Estado", - "content_type": 67, - "codename": "add_estado" + "name": "Exclusão de city", + "content_type": 70, + "codename": "delete_city" } }, { "model": "auth.permission", - "pk": 305, + "pk": 327, "fields": { - "name": "Can change Estado", - "content_type": 67, - "codename": "change_estado" + "name": "Mostrar menu de Dados auxiliares", + "content_type": 17, + "codename": "menu_dados_auxiliares" } }, { "model": "auth.permission", - "pk": 306, + "pk": 328, "fields": { - "name": "Can delete Estado", - "content_type": 67, - "codename": "delete_estado" + "name": "Mostrar menu de Grupos de Contatos", + "content_type": 17, + "codename": "menu_grupocontatos" } }, { "model": "auth.permission", - "pk": 307, + "pk": 329, "fields": { - "name": "Visualiza\u00e7ao da lista de Estados", - "content_type": 67, - "codename": "list_estado" + "name": "Mostrar menu de Impressos de endere\u00e7amento", + "content_type": 17, + "codename": "menu_impresso_enderecamento" } }, { "model": "auth.permission", - "pk": 308, + "pk": 330, "fields": { - "name": "Visualiza\u00e7\u00e3o dos detalhes de Estados", - "content_type": 67, - "codename": "detail_estado" + "name": "Exibição de Menu de Relat\u00f3rios", + "content_type": 17, + "codename": "menu_relatorios" } }, { "model": "auth.permission", - "pk": 309, + "pk": 331, "fields": { - "name": "Can add country", - "content_type": 68, - "codename": "add_country" + "name": "Mostrar menu de Tabelas auxiliares", + "content_type": 17, + "codename": "menu_tabelas_auxiliares" } }, { "model": "auth.permission", - "pk": 310, + "pk": 332, "fields": { - "name": "Can change country", - "content_type": 68, - "codename": "change_country" + "name": "Mostrar menu de de Contatos", + "content_type": 17, + "codename": "menu_contatos" } }, { "model": "auth.permission", - "pk": 311, + "pk": 333, "fields": { - "name": "Can delete country", - "content_type": 68, - "codename": "delete_country" + "name": "Mostrar menu de Áreas de trabalho", + "content_type": 17, + "codename": "menu_area_trabalho" } }, { "model": "auth.permission", - "pk": 312, + "pk": 334, "fields": { - "name": "Can add region/state", - "content_type": 69, - "codename": "add_region" + "name": "Mostrar menu de Processos", + "content_type": 17, + "codename": "menu_processos" } }, { "model": "auth.permission", - "pk": 313, + "pk": 340, "fields": { - "name": "Can change region/state", - "content_type": 69, - "codename": "change_region" + "name": "Exclusão de Agenda", + "content_type": 75, + "codename": "add_evento" } }, { "model": "auth.permission", - "pk": 314, + "pk": 341, "fields": { - "name": "Can delete region/state", - "content_type": 69, - "codename": "delete_region" + "name": "Exclusão de Agenda", + "content_type": 75, + "codename": "change_evento" } }, { "model": "auth.permission", - "pk": 315, + "pk": 342, "fields": { - "name": "Can add city", - "content_type": 70, - "codename": "add_city" + "name": "Exclusão de Agenda", + "content_type": 75, + "codename": "delete_evento" } }, { "model": "auth.permission", - "pk": 316, + "pk": 343, "fields": { - "name": "Can change city", - "content_type": 70, - "codename": "change_city" + "name": "Visualiza\u00e7\u00e3o dos detalhes de Agenda", + "content_type": 75, + "codename": "detail_evento" } }, { "model": "auth.permission", - "pk": 317, + "pk": 344, "fields": { - "name": "Can delete city", - "content_type": 70, - "codename": "delete_city" + "name": "Visualiza\u00e7ao da lista de Agenda", + "content_type": 75, + "codename": "list_evento" } }, { "model": "auth.permission", - "pk": 318, + "pk": 345, "fields": { - "name": "Can add CRUD event", - "content_type": 71, - "codename": "add_crudevent" + "name": "Mostrar menu de Agenda", + "content_type": 11, + "codename": "menu_agenda" } }, { "model": "auth.permission", - "pk": 319, + "pk": 346, "fields": { - "name": "Can change CRUD event", - "content_type": 71, - "codename": "change_crudevent" + "name": "Mostrar menu de Correspondências", + "content_type": 11, + "codename": "menu_correspondencias" } }, { "model": "auth.permission", - "pk": 320, + "pk": 347, "fields": { - "name": "Can delete CRUD event", - "content_type": 71, - "codename": "delete_crudevent" + "name": "Mostrar menu de Permissões", + "content_type": 11, + "codename": "menu_permissoes" } }, { "model": "auth.permission", - "pk": 321, + "pk": 348, "fields": { - "name": "Can add login event", - "content_type": 72, - "codename": "add_loginevent" + "name": "Mostrar menu de Sistema", + "content_type": 11, + "codename": "menu_sistema" } }, { "model": "auth.permission", - "pk": 322, + "pk": 349, "fields": { - "name": "Can change login event", - "content_type": 72, - "codename": "change_loginevent" + "name": "Exclusão de AuditLog", + "content_type": 76, + "codename": "add_auditlog" } }, { "model": "auth.permission", - "pk": 323, + "pk": 350, "fields": { - "name": "Can delete login event", - "content_type": 72, - "codename": "delete_loginevent" + "name": "Exclusão de AuditLog", + "content_type": 76, + "codename": "change_auditlog" } }, { "model": "auth.permission", - "pk": 324, + "pk": 351, "fields": { - "name": "Can add request event", - "content_type": 73, - "codename": "add_requestevent" + "name": "Exclusão de AuditLog", + "content_type": 76, + "codename": "delete_auditlog" } }, { "model": "auth.permission", - "pk": 325, + "pk": 352, "fields": { - "name": "Can change request event", - "content_type": 73, - "codename": "change_requestevent" + "name": "Visualiza\u00e7\u00e3o dos detalhes de AuditLogs", + "content_type": 76, + "codename": "detail_auditlog" } }, { "model": "auth.permission", - "pk": 326, + "pk": 353, "fields": { - "name": "Can delete request event", - "content_type": 73, - "codename": "delete_requestevent" + "name": "Visualiza\u00e7ao da lista de AuditLogs", + "content_type": 76, + "codename": "list_auditlog" } } ] diff --git a/config/initial_data/django_content_type.sql b/config/initial_data/django_content_type.sql index fcddc45..3c9d256 100644 --- a/config/initial_data/django_content_type.sql +++ b/config/initial_data/django_content_type.sql @@ -19,82 +19,71 @@ DELETE FROM public.django_admin_log; DELETE FROM public.django_content_type; COPY public.django_content_type (id, app_label, model) FROM stdin; -1 admin logentry -2 auth permission -3 auth group -4 contenttypes contenttype -5 sessions session -6 easy_thumbnails source -7 easy_thumbnails thumbnail -8 easy_thumbnails thumbnaildimensions -9 taggit tag -10 taggit taggeditem -11 core user -12 core municipio -13 core nivelinstrucao -14 core situacaomilitar -15 core parlamentar -16 core partido -17 core areatrabalho -18 core operadorareatrabalho -19 core cep -20 core regiaomunicipal -21 core distrito -22 core bairro -23 core tipologradouro -24 core logradouro -25 core trecho -26 core impressoenderecamento -27 core filiacao -28 cerimonial tipotelefone -29 cerimonial tipoendereco -30 cerimonial tipoemail -31 cerimonial parentesco -32 cerimonial estadocivil -33 cerimonial pronometratamento -34 cerimonial tipoautoridade -35 cerimonial tipolocaltrabalho -36 cerimonial nivelinstrucao -37 cerimonial operadoratelefonia -38 cerimonial contato -39 cerimonial perfil -40 cerimonial telefone -41 cerimonial telefoneperfil -42 cerimonial email -43 cerimonial emailperfil -44 cerimonial dependente -45 cerimonial dependenteperfil -46 cerimonial localtrabalho -47 cerimonial localtrabalhoperfil -48 cerimonial endereco -49 cerimonial enderecoperfil -50 cerimonial filiacaopartidaria -51 cerimonial statusprocesso -52 cerimonial classificacaoprocesso -53 cerimonial topicoprocesso -54 cerimonial assuntoprocesso -55 cerimonial processo -56 cerimonial processocontato -57 cerimonial grupodecontatos -58 social_auth usersocialauth -59 social_auth nonce -60 social_auth association -61 social_auth code -62 social_django usersocialauth -63 social_django nonce -64 social_django association -65 social_django code -66 social_django partial -67 core estado -68 cities_light country -69 cities_light region -70 cities_light city -71 easy_audit crudevent -72 easy_audit loginevent -73 easy_audit requestevent +1 admin logentry +2 auth permission +3 auth group +4 contenttypes contenttype +5 sessions session +6 easy_thumbnails source +7 easy_thumbnails thumbnail +8 easy_thumbnails thumbnaildimensions +9 taggit tag +10 taggit taggeditem +11 core user +12 core municipio +13 core nivelinstrucao +14 core situacaomilitar +15 core parlamentar +16 core partido +17 core areatrabalho +18 core operadorareatrabalho +19 core cep +20 core regiaomunicipal +21 core distrito +22 core bairro +23 core tipologradouro +24 core logradouro +25 core trecho +26 core impressoenderecamento +27 core filiacao +28 cerimonial tipotelefone +29 cerimonial tipoendereco +30 cerimonial tipoemail +31 cerimonial parentesco +32 cerimonial estadocivil +33 cerimonial pronometratamento +34 cerimonial tipoautoridade +35 cerimonial tipolocaltrabalho +36 cerimonial nivelinstrucao +37 cerimonial operadoratelefonia +38 cerimonial contato +39 cerimonial perfil +40 cerimonial telefone +41 cerimonial telefoneperfil +42 cerimonial email +43 cerimonial emailperfil +44 cerimonial dependente +45 cerimonial dependenteperfil +46 cerimonial localtrabalho +47 cerimonial localtrabalhoperfil +48 cerimonial endereco +49 cerimonial enderecoperfil +50 cerimonial filiacaopartidaria +51 cerimonial statusprocesso +52 cerimonial classificacaoprocesso +53 cerimonial topicoprocesso +54 cerimonial assuntoprocesso +55 cerimonial processo +56 cerimonial processocontato +57 cerimonial grupodecontatos +67 core estado +68 cities_light country +69 cities_light region +70 cities_light city +75 cerimonial evento +76 core auditlog \. - -- -- Name: django_content_type_id_seq; Type: SEQUENCE SET; Schema: public; Owner: saap -- diff --git a/docker/Dockerfile b/docker/Dockerfile index bf7edfa..8b5795d 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -62,7 +62,6 @@ CMD rm /usr/local/lib/python*/site-packages/rest_framework/* -R RUN cp /var/interlegis/saap/config/django_db_models/base.py /usr/local/lib/python*/site-packages/django/db/models/ RUN cp /var/interlegis/saap/config/django_core_management/base.py /usr/local/lib/python*/site-packages/django/core/management/ RUN cp /var/interlegis/saap/config/rest_framework/* /usr/local/lib/python*/site-packages/rest_framework/ -R -RUN cp /var/interlegis/saap/config/bootstrap_admin/filter.html /usr/local/lib/python*/site-packages/bootstrap_admin/templates/admin/ RUN cp /var/interlegis/saap/config/smart-selects/* /usr/local/lib/python*/site-packages/smart_selects/static/smart-selects/admin/js/ RUN cp /var/interlegis/saap/config/reportlab/* /usr/local/lib/python*/site-packages/reportlab/platypus/ RUN cp /var/interlegis/saap/config/image_cropping/* /usr/local/lib/python*/site-packages/image_cropping diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 094c130..56af17a 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -10,7 +10,7 @@ services: POSTGRES_PASSWORD: saap POSTGRES_USER: saap POSTGRES_DB: saap - PGDATA : /var/lib/postgresql/data/ + PGDATA: /var/lib/postgresql/data/ volumes: - saapdb_data:/var/lib/postgresql/data/ ports: @@ -18,7 +18,8 @@ services: networks: - saap-net saap: - image: interlegis/saap:latest +# image: interlegis/saap:latest + image: ojonathacardoso/saap:latest # build: # context: . # dockerfile: Dockerfile diff --git a/docker/start.sh b/docker/start.sh index b458c9e..a70b272 100644 --- a/docker/start.sh +++ b/docker/start.sh @@ -55,9 +55,6 @@ load_db() { echo "[LOAD_DB] Creating database structure..." yes yes | python3 manage.py migrate - echo "[LOAD_DB] Loading initial data..." - python3 manage.py loaddata /var/interlegis/saap/config/initial_data/*.json - echo "[LOAD_DB] Creating extension..." psql -h saapdb -c "CREATE EXTENSION unaccent;" diff --git a/docs/deploy.rst b/docs/deploy.rst index 60e0c46..a349093 100644 --- a/docs/deploy.rst +++ b/docs/deploy.rst @@ -33,26 +33,16 @@ Com isto, ele coletará todos os arquivos estáticos do projeto e os guardará n 3) Instalar pacotes ---------------------------------------------------------------------------------------- -Instale o NGINX: +Instale o NGINX e o Supervisor :: - sudo apt-get install nginx -y + sudo apt-get install nginx supervisor -y -Em seguida, instale o Gunicorn: +Lembrando que o Gunicorn já foi adicionado nas dependências, durante o processo de instalação pra desenvolvimento -:: - sudo pip3 install gunicorn - -Por fim, instale o Supervisor: - -:: - - sudo apt-get install supervisor -y - - -3) Preparar o NGINX +4) Preparar o NGINX ---------------------------------------------------------------------------------------- Crie o arquivo de configuração: @@ -111,7 +101,7 @@ Em seguida, é necessário criar o link simbólico para este arquivo que criamos sudo ln -s /etc/nginx/sites-available/saap.conf /etc/nginx/sites-enabled/saap -4) Preparar o Gunicorn +5) Preparar o Gunicorn ---------------------------------------------------------------------------------------- Nesse passo, você deve estar atento para duas variáveis, que podem ser manipuladas: diff --git a/docs/docker.rst b/docs/docker.rst index b232d01..9809bc5 100644 --- a/docs/docker.rst +++ b/docs/docker.rst @@ -68,7 +68,25 @@ Se a opção ``BRASAO_PROPRIO`` está com ``True``, é necessário atualizar a i :: - docker cp brasao-camara.png saap:/var/interlegis/saap/saap/static/img/brasao-camara.png + sudo docker cp brasao-camara.png saap:/var/interlegis/saap/saap/static/img/brasao-camara.png + + +5) Fazer a carga inicial do banco +---------------------------------------------------------------------------------------- + +Para que o sistema esteja com os dados iniciais, além das configurações de permissões, deve-se rodar os comandos a seguir, na ordem: + +:: + + sudo docker cp saap:config/initial_data/django_content.type.sql . + sudo docker exec -i postgres psql -U saap -d saap < django_content_type.sql + +:: + + sudo docker exec -i saap bash + ./manage.py loaddata config/initial_data/auth_permission.json + ./manage.py loaddata config/initial_data/auth_group.json + ./manage.py loaddata config/initial_data/saap_*.json Parar imagens @@ -89,7 +107,7 @@ Para realizar o backup do banco do SAAP, basta rodar o seguinte comando: :: - docker exec postgres pg_dump -U saap -v -Fc saap > ~/saap.dump + sudo docker exec postgres pg_dump -U saap -v -Fc saap > ~/saap.dump O destino e o nome do arquivo gerado são personalizáveis. @@ -100,15 +118,15 @@ Para realizar a restauraçao do banco, é necessário previamente limpar o banco :: - docker exec postgres psql -U saap -c 'DROP SCHEMA PUBLIC CASCADE;' - docker exec postgres psql -U saap -c 'CREATE SCHEMA PUBLIC;' + sudo docker exec postgres psql -U saap -c 'DROP SCHEMA PUBLIC CASCADE;' + sudo docker exec postgres psql -U saap -c 'CREATE SCHEMA PUBLIC;' Em seguida, basta copiar o arquivo para dentro da imagem e fazer a importação: :: - docker cp saap.dump postgres:/tmp/ - docker exec postgres pg_restore -v -U saap -d saap /tmp/saap.dump + sudo docker cp saap.dump postgres:/tmp/ + sudo docker exec postgres pg_restore -v -U saap -d saap /tmp/saap.dump Atualizar imagem ---------------------------------------------------------------------------------------- diff --git a/docs/instalacao.rst b/docs/instalacao.rst index 5437414..48888ee 100644 --- a/docs/instalacao.rst +++ b/docs/instalacao.rst @@ -115,6 +115,10 @@ As configurações e instruções de uso para o Git estão espalhadas pela Inter mkvirtualenv -a /var/interlegis/saap -p python3 -r requirements/requirements.txt saap +:: + + pip install -r /var/interlegis/saap/requirements/dev-requirements.txt + 5) Configurar o banco de dados PostgreSQL ----------------------------------------------------- @@ -266,12 +270,6 @@ Lembrando, antes, que [PYTHON] deve ser trocada pela pasta com a versão do Pyth cp /var/interlegis/saap/config/rest_framework/* /var/interlegis/.virtualenvs/saap/lib/[PYTHON]/site-packages/rest_framework/ -R -* Bootstrap - -:: - - cp /var/interlegis/saap/config/bootstrap_admin/filter.html /var/interlegis/.virtualenvs/saap/lib/[PYTHON]/site-packages/bootstrap_admin/templates/admin/ - * Smart Selects (usado para carregar os campos de Estado, Município, Bairro...) :: @@ -323,8 +321,10 @@ Após isto, é necessário fazer a carga de dados básicos. Para isto, rode os c sudo -u postgres psql saap < config/initial_data/django_content_type.sql :: - - ./manage.py loaddata config/initial_data/*.json + + ./manage.py loaddata config/initial_data/auth_permission.json + ./manage.py loaddata config/initial_data/auth_group.json + ./manage.py loaddata config/initial_data/saap*.json Para concluir, é necessário criar o super-usuário, que terá permissão de admin. Ele solicitará e-mail e senha. diff --git a/requirements/dev-requirements.txt b/requirements/dev-requirements.txt index 939f993..6ee8893 100644 --- a/requirements/dev-requirements.txt +++ b/requirements/dev-requirements.txt @@ -1,6 +1,2 @@ --r test-requirements.txt -autopep8==1.2.2 -beautifulsoup4==4.4.1 -ipdb==0.9.0 -pygraphviz==1.3rc2 -pytest-ipdb==0.1-prerelease2 + +django-debug-toolbar==1.5 diff --git a/requirements/requirements.txt b/requirements/requirements.txt index 04f14a9..b61c752 100644 --- a/requirements/requirements.txt +++ b/requirements/requirements.txt @@ -1,12 +1,10 @@ -bootstrap-admin -dj-database-url==0.4.1 +django>=1.9,<1.10 +django-admin-bootstrapped django-bootstrap3==7.0.1 django-bower==5.1.0 django-braces==1.8.1 django-compressor==2.0 django-crispy-forms==1.6.0 -django-debug-toolbar==1.5 -django-easy-audit==1.0 django-exclusivebooleanfield django-extensions==1.6.1 django-extra-views==0.7.1 @@ -18,8 +16,8 @@ django-modelcluster==2.0 django-sass-processor==0.3.4 django-smart-selects django-taggit==0.21.2 -django>=1.9,<1.10 djangorestframework==3.9.1 +dj-database-url==0.4.1 easy-thumbnails==2.3 trml2pdf gunicorn==19.5.0 @@ -30,11 +28,9 @@ pyjwkest python-dateutil python-decouple==3.0 python-magic==0.4.10 -python-social-auth pytz==2016.3 pyyaml==5.1 rtyaml==0.0.2 -social-auth-app-django==4 sqlparse==0.2.0 unipath==1.1 xlwt diff --git a/saap/cerimonial/forms.py b/saap/cerimonial/forms.py index e09607e..5626298 100644 --- a/saap/cerimonial/forms.py +++ b/saap/cerimonial/forms.py @@ -12,7 +12,7 @@ from django.db import models from django.db.models import Q, F, Func, Value #from django.forms.extras.widgets import SelectDateWidget -from django.forms.widgets import SelectDateWidget, DateInput +from django.forms.widgets import SelectDateWidget, DateInput, DateTimeInput, RadioSelect from django.forms import DateInput from django.forms.models import ModelForm, ModelMultipleChoiceField @@ -149,11 +149,19 @@ def __init__(self, *args, **kwargs): self.fields['principal'].inline_class = True - class EventoForm(ModelForm): + simultaneo = forms.TypedChoiceField( + label="Ignorar eventos simultâneos?", + required=False, + coerce=lambda x: x == 'True', + choices=((False, 'Não'), (True, 'Sim')), + widget=forms.RadioSelect + ) + class Meta: model = Evento + fields = ['titulo', 'descricao', 'localizacao', @@ -161,27 +169,21 @@ class Meta: 'municipio', 'bairro', 'inicio', - 'termino', - 'workspace'] - + 'termino', + 'simultaneo', + 'workspace', + ] + # datetime-local is a HTML5 input type, format to make date time show on fields widgets = { - 'inicio': DateInput(attrs={'type': 'datetime-local'}, format='%Y-%m-%dT%H:%M'), - 'termino': DateInput(attrs={'type': 'datetime-local'}, format='%Y-%m-%dT%H:%M'), + 'inicio': DateTimeInput(attrs={'type': 'datetime-local'}, format='%Y-%m-%dT%H:%M'), + 'termino': DateTimeInput(attrs={'type': 'datetime-local'}, format='%Y-%m-%dT%H:%M'), } def __init__(self, *args, **kwargs): - workspace = kwargs.pop('workspace') - super(EventoForm, self).__init__(*args, **kwargs) - for field in self.fields.values(): - field.widget.attrs.update({'class': 'form-control'}) - - self.workspace = workspace - self.initial['workspace'] = self.workspace - # input_formats parses HTML5 datetime-local input to datetime field self.fields['inicio'].input_formats = ('%Y-%m-%dT%H:%M',) self.fields['termino'].input_formats = ('%Y-%m-%dT%H:%M',) @@ -196,6 +198,28 @@ def clean(self): if termino <= inicio: self._errors['termino'] = [_('O término do evento deve ser posterior ao seu início.')] + if self.cleaned_data['simultaneo'] != True: + + inicio_concomitante = Evento.objects.filter(workspace=self.initial['workspace'], + inicio__lte=self.cleaned_data['inicio'], termino__gte=self.cleaned_data['inicio']) + + if self.instance.pk != None: + inicio_concomitante = inicio_concomitante.filter(~Q(pk=self.instance.pk)) + + if inicio_concomitante.count() > 0: + self._errors['inicio'] = [_('Há ' + str(inicio_concomitante.count()) + ' evento(s) marcado(s) para essa data/hora de início.')] + self._errors['simultaneo'] = [_('Para ignorar a verificação de eventos simultâneos, marque Sim nessa opção')] + + termino_concomitante = Evento.objects.filter(workspace=self.initial['workspace'], + inicio__lte=self.cleaned_data['termino'], termino__gte=self.cleaned_data['termino']) + + if self.instance.pk != None: + termino_concomitante = termino_concomitante.filter(~Q(pk=self.instance.pk)) + + if termino_concomitante.count() > 0: + self._errors['termino'] = [_('Há ' + str(termino_concomitante.count()) + ' evento(s) marcado(s) para esta data/hora de término.')] + self._errors['simultaneo'] = [_('Para ignorar a verificação de eventos simultâneos, marque Sim nessa opção')] + class ContatoForm(ModelForm): class Meta: @@ -3163,6 +3187,7 @@ def __init__(self, data=None, ('telefone', 4), ('tipo_autoridade', 4), ('cargo', 4), + ('pk_selecionados', 12), ]) col2 = to_row([ @@ -3609,6 +3634,191 @@ def __init__(self, data=None, +class EventoFilterSet(FilterSet): + + filter_overrides = {models.DateTimeField: { + 'filter_class': MethodFilter, + 'extra': lambda f: { + 'label': '%s (%s)' % (f.verbose_name, _('período')), + 'widget': RangeWidgetOverride} + }} + + + search = MethodFilter() + + bairro = MethodModelMultipleChoiceFilter( + required=False, + label=_('Bairro (' + settings.DADOS_MUNICIPIO + ')'), + queryset=None) # Será carregado no final do código + + municipio = MethodModelMultipleChoiceFilter( + required=False, + label=_('Município (' + settings.DADOS_UF + ')'), + queryset=None) # Será carregado no final do código + + pk_selecionados = MethodFilter( + required=False, + action=filter_pk_selecionados, + ) + + + def filter_search(self, queryset, value): + + query = normalize(value) + + query = query.split(' ') + if query: + q = Q() + for item in query: + if not item: + continue + # Remove acentos dos campos que estão no banco + q = q & Q(search__unaccent__icontains=item) + + if q: + queryset = queryset.filter(q) + return queryset + + def filter_search(self, queryset, value): + + query = normalize(value) + + query = query.split(' ') + if query: + q = Q() + for item in query: + if not item: + continue + # Remove acentos dos campos que estão no banco + q = q & (Q(title__unaccent__icontains=item) | + Q(description__unaccent__icontains=item) | + Q(location__unaccent__icontains=item)) + + if q: + queryset = queryset.filter(q) + return queryset + + + def filter_inicio(self, queryset, value): + + if not value[0] and not value[1]: + return queryset + + inicial = None + final = None + + if(value[0] != ''): + inicial = datetime.datetime.strptime(value[0], "%d/%m/%Y").date() + if(value[1] != ''): + final = datetime.datetime.strptime(value[1], "%d/%m/%Y").date() + + if(inicial != None and final != None): + if inicial > final: + inicial, final = final, inicial + range_select = Q(inicio__range=[inicial, final]) + elif(inicial != None): + range_select = Q(inicio__gte=inicial) + elif(final != None): + range_select = Q(inicio__lte=final) + + # Run the query. + return queryset.filter(range_select) + + def filter_termino(self, queryset, value): + + if not value[0] and not value[1]: + return queryset + + inicial = None + final = None + + if(value[0] != ''): + inicial = datetime.datetime.strptime(value[0], "%d/%m/%Y").date() + if(value[1] != ''): + final = datetime.datetime.strptime(value[1], "%d/%m/%Y").date() + + if(inicial != None and final != None): + if inicial > final: + inicial, final = final, inicial + range_select = Q(termino__range=[inicial, final]) + elif(inicial != None): + range_select = Q(termino__gte=inicial) + elif(final != None): + range_select = Q(termino__lte=final) + + # Run the query. + return queryset.filter(range_select) + + def filter_bairro(self, queryset, value): + if value: + queryset = queryset.filter( + bairro__in=value).distinct() + + return queryset + + def filter_municipio(self, queryset, value): + if value: + queryset = queryset.filter( + municipio__in=value).distinct() + + return queryset + + class Meta: + model = Evento + fields = ['search', + 'inicio', + 'termino', + ] + + def __init__(self, data=None, + queryset=None, prefix=None, strict=None, **kwargs): + + workspace = kwargs.pop('workspace') + + super(EventoFilterSet, self).__init__( + data=data, + queryset=queryset, prefix=prefix, strict=strict, **kwargs) + + fields = to_row([ + ('search', 12), + ('inicio', 6), + ('termino', 6), + ('bairro', 6), + ('municipio', 6), + ('pk_selecionados', 12), + ]) + + row = to_row([( + Fieldset( + _('Busca por Evento'), + fields, + to_row([ + (SubmitFilterPrint( + 'filter', + value=_('Filtrar'), + css_class='btn-default pull-right', + type='submit'),2), + (SubmitFilterPrint( + 'print', + value=_('Imprimir'), + css_class='btn-primary pull-right', + type='submit'),2) + ])), 12),]) + + self.form.helper = FormHelper() + self.form.helper.form_method = 'GET' + self.form.helper.layout = Layout( + row, + ) + + self.form.fields['pk_selecionados'].label = _('Códigos selecionados') + self.form.fields['search'].label = 'Título, descrição ou localização' + self.form.fields['inicio'].label = 'Início do evento (intervalo de datas)' + self.form.fields['termino'].label = 'Término do evento (intervalo de datas)' + + self.form.fields['bairro'].queryset = Bairro.objects.filter(municipio=Municipio.objects.get(nome=settings.DADOS_MUNICIPIO, estado=Estado.objects.get(sigla=settings.DADOS_UF)).pk) + self.form.fields['municipio'].queryset = Municipio.objects.filter(estado=Estado.objects.get(sigla=settings.DADOS_UF).pk) + class AgendaFilterSet(FilterSet): @@ -3616,7 +3826,7 @@ class AgendaFilterSet(FilterSet): filter_overrides = {models.DateTimeField: { 'filter_class': MethodFilter, 'extra': lambda f: { - 'label': '%s (%s)' % (f.verbose_name, _('período')), + 'label': '%s (%s)' % (f.verbose_name, _('intervalo de datas')), 'widget': RangeWidgetOverride} }} @@ -3797,8 +4007,8 @@ def __init__(self, data=None, ) self.form.fields['search'].label = 'Título, descrição ou localização' - self.form.fields['inicio'].label = 'Início do evento (período)' - self.form.fields['termino'].label = 'Término do evento (período)' + self.form.fields['inicio'].label = 'Início do evento (intervalo de datas)' + self.form.fields['termino'].label = 'Término do evento (intervalo de datas)' self.form.fields['bairro'].queryset = Bairro.objects.filter(municipio=Municipio.objects.get(nome=settings.DADOS_MUNICIPIO, estado=Estado.objects.get(sigla=settings.DADOS_UF)).pk) self.form.fields['municipio'].queryset = Municipio.objects.filter(estado=Estado.objects.get(sigla=settings.DADOS_UF).pk) diff --git a/saap/cerimonial/migrations/0091_auto_20220531_1341.py b/saap/cerimonial/migrations/0091_auto_20220531_1341.py new file mode 100644 index 0000000..b7423db --- /dev/null +++ b/saap/cerimonial/migrations/0091_auto_20220531_1341.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.13 on 2022-05-31 16:41 +from __future__ import unicode_literals + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +from django.utils.timezone import utc + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('cerimonial', '0090_auto_20220516_1715'), + ] + + operations = [ + migrations.AddField( + model_name='evento', + name='created', + field=models.DateTimeField(auto_now_add=True, default=datetime.datetime(2022, 5, 31, 16, 40, 46, 550931, tzinfo=utc), verbose_name='created'), + preserve_default=False, + ), + migrations.AddField( + model_name='evento', + name='modified', + field=models.DateTimeField(auto_now=True, default=datetime.datetime(2022, 5, 31, 16, 40, 51, 279135, tzinfo=utc), verbose_name='modified'), + preserve_default=False, + ), + migrations.AddField( + model_name='evento', + name='modifier', + field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.PROTECT, related_name='+', to=settings.AUTH_USER_MODEL, verbose_name='modifier'), + preserve_default=False, + ), + migrations.AddField( + model_name='evento', + name='owner', + field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.PROTECT, related_name='+', to=settings.AUTH_USER_MODEL, verbose_name='owner'), + preserve_default=False, + ), + ] diff --git a/saap/cerimonial/migrations/0092_auto_20220601_0925.py b/saap/cerimonial/migrations/0092_auto_20220601_0925.py new file mode 100644 index 0000000..ac96b76 --- /dev/null +++ b/saap/cerimonial/migrations/0092_auto_20220601_0925.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.13 on 2022-06-01 12:25 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('cerimonial', '0091_auto_20220531_1341'), + ] + + operations = [ + migrations.AlterField( + model_name='evento', + name='workspace', + field=models.ForeignKey(default=16, on_delete=django.db.models.deletion.PROTECT, to='core.AreaTrabalho', verbose_name='Área de trabalho'), + preserve_default=False, + ), + ] diff --git a/saap/cerimonial/models.py b/saap/cerimonial/models.py index 554b3da..ea38d68 100644 --- a/saap/cerimonial/models.py +++ b/saap/cerimonial/models.py @@ -13,11 +13,8 @@ from django.utils import timezone -from django.core.urlresolvers import reverse - from exclusivebooleanfield.fields import ExclusiveBooleanField -from pytz import timezone as pytz_timezone FEMININO = 'F' MASCULINO = 'M' @@ -209,23 +206,38 @@ class Meta(DescricaoAbstractModel.Meta): verbose_name = _('Operadora de telefonia') verbose_name_plural = _('Operadoras de telefonia') -#class Evento(SaapAuditoriaModelMixin): -class Evento(models.Model): +class Evento(SaapAuditoriaModelMixin): - titulo = models.CharField(max_length=200, default='Evento', blank=False, verbose_name=_('Título')) + titulo = models.CharField( + max_length=200, + default='Evento', + blank=False, + verbose_name=_('Título')) - descricao = models.TextField(blank=True, default='', verbose_name=_('Descrição')) + descricao = models.TextField( + blank=True, + default='', + verbose_name=_('Descrição')) - localizacao = models.TextField(blank=True, default='', verbose_name=_('Localização')) + localizacao = models.TextField( + blank=True, + default='', + verbose_name=_('Localização')) - inicio = models.DateTimeField(default=timezone.now, blank=False, verbose_name=_('Início')) + inicio = models.DateTimeField( + default=timezone.now, + blank=False, + verbose_name=_('Início')) - termino = models.DateTimeField(default=timezone.now, blank=False, verbose_name=_('Término')) + termino = models.DateTimeField( + default=timezone.now, + blank=False, + verbose_name=_('Término')) workspace = models.ForeignKey( AreaTrabalho, verbose_name=_('Área de trabalho'), - blank=True, null=True, on_delete=PROTECT) + blank=False, null=False, on_delete=PROTECT) estado = models.ForeignKey( Estado, @@ -259,34 +271,11 @@ class Meta(): @cached_property def fields_search(self): - return ['title', - 'description',] - - @property - def get_html_url(self): - url = reverse('saap.cerimonial:evento_edit', args=(self.id,)) - fmt = "%d/%m/%Y às %H:%M" - self.inicio = self.inicio.astimezone(pytz_timezone('America/Sao_Paulo')) - self.termino = self.termino.astimezone(pytz_timezone('America/Sao_Paulo')) - - if(self.bairro != None): - str_bairro = self.bairro.nome - else: - str_bairro = '' - - if(self.municipio != None): - str_municipio = self.municipio.nome - else: - str_municipio = '' + return ['titulo', + 'descricao',] - text = "Descrição: " + self.descricao + "\n\n" + \ - "Local: " + self.localizacao + "\n" + \ - "Bairro: " + str_bairro + "\n" + \ - "Município: " + str_municipio + "\n\n" + \ - "Início: " + self.inicio.strftime(fmt) + "\n" + \ - "Término: " + self.termino.strftime(fmt) - hora_inicio = self.inicio.strftime("%H:%M") - return f' {hora_inicio} {self.titulo}' + def __str__(self): + return self.titulo class Contato(SaapSearchMixin, SaapAuditoriaModelMixin): @@ -901,8 +890,8 @@ class Meta: verbose_name = _('Endereço do perfil') verbose_name_plural = _('Endereços do perfil') - def get_absolute_url(self): - return reverse('view_mymodel', args=(self.pk,)) +# def get_absolute_url(self): +# return reverse('view_mymodel', args=(self.pk,)) class FiliacaoPartidaria(SaapAuditoriaModelMixin): diff --git a/saap/cerimonial/reports.py b/saap/cerimonial/reports.py index 884e370..1a51233 100644 --- a/saap/cerimonial/reports.py +++ b/saap/cerimonial/reports.py @@ -28,7 +28,8 @@ from reportlab.lib.units import mm from saap.cerimonial.forms import ImpressoEnderecamentoFilterSet,\ - ProcessosFilterSet, ContatosFilterSet, ContatosExportaFilterSet, ProcessoIndividualFilterSet, ContatoIndividualFilterSet, MalaDiretaFilterSet, AgendaFilterSet + ProcessosFilterSet, ContatosFilterSet, ContatosExportaFilterSet, ProcessoIndividualFilterSet, ContatoIndividualFilterSet, \ + MalaDiretaFilterSet, AgendaFilterSet, EventoFilterSet from saap.cerimonial.models import Contato, Processo, Telefone, Email, GrupoDeContatos, Endereco, \ AssuntoProcesso, TopicoProcesso, LocalTrabalho, Dependente, FiliacaoPartidaria, \ Bairro, Municipio, Estado, IMPORTANCIA_CHOICE, Evento @@ -3015,7 +3016,7 @@ def get_context_data(self, **kwargs): fmt = "%d/%m/%Y às %H:%M" agenda.inicio = agenda.inicio.strftime(fmt) agenda.termino = agenda.termino.strftime(fmt) - agenda.url = reverse('saap.cerimonial:evento_edit', args=(agenda.id,)) + agenda.url = "/eventos/" + str(agenda.id) return context @@ -3182,26 +3183,6 @@ def get_data(self): return agenda -# def validate_data(self): -# contatos = [] -# consulta_agregada = self.object_list.order_by('nome',) -# consulta_agregada = consulta_agregada.values_list( -# 'id', -# ) -# -# total_erros = 0 -# -# for contato in consulta_agregada.all(): -# query = (Q(permite_contato=True)) -# query.add(Q(contato__id=contato[0]), Q.AND) -# -# email = Email.objects.filter(query).count() -# -# if(email == 0): -# total_erros = total_erros + 1 -# -# return total_erros - def set_cabec(self, h5): cabec = [Paragraph(_('Título'), h5)] cabec.append(Paragraph(_('Descrição'), h5)) @@ -3221,7 +3202,316 @@ def add_relat_title(self, corpo_relatorio): corpo_relatorio.append(self.cabec) +# +# +# +# +# +# +# +# +# +# + +class RelatorioEventoView(PermissionRequiredMixin, FilterView): + #permission_required = 'cerimonial.print_rel_agenda' + #permission_required = 'core.menu_agenda' + permission_required = 'core.menu_contatos' + filterset_class = EventoFilterSet + model = Evento + template_name = "cerimonial/filter_evento.html" + container_field = 'workspace__operadores' + + paginate_by = 100 + + def __init__(self): + super().__init__() + self.ctx_title = 'Relatório detalhado de um evento' + self.relat_title = 'Detalhamento de Informações do Evento' + self.nome_objeto = 'Evento' + self.filename = 'Detalhamento_Evento' + + @cached_property + def is_contained(self): + return True + + @property + def verbose_name(self): + return self.model._meta.verbose_name + + @property + def verbose_name_plural(self): + return self.model._meta.verbose_name_plural + + def get(self, request, *args, **kwargs): + filterset_class = self.get_filterset_class() + self.filterset = self.get_filterset(filterset_class) + + self.object_list = self.filterset.qs + + if len(request.GET) and not len(self.filterset.form.errors)\ + and not self.object_list.exists(): + messages.error(request, _( + 'Não existe {} com as ' + 'condições definidas na busca!'.format(self.nome_objeto) + )) + + if 'print' in request.GET and self.object_list.exists(): + if self.filterset.form.cleaned_data['pk_selecionados']: + filename = str(self.filename) + "_" + str(datetime.datetime.fromtimestamp(time.time()).strftime('%Y_%m_%d_%H_%M_%S')) + response = HttpResponse(content_type='application/pdf') + content = 'inline; filename="%s.pdf"' % filename + response['Content-Disposition'] = content + self.build_pdf(response) + return response + else: + messages.error(request, _('Não há Evento selecionado. Marque ao menos um contato para gerar o relatório')) + + context = self.get_context_data(filter=self.filterset, + object_list=self.object_list) + return self.render_to_response(context) + + def get_filterset(self, filterset_class): + kwargs = self.get_filterset_kwargs(filterset_class) + try: + kwargs['workspace'] = AreaTrabalho.objects.filter( + operadores=self.request.user.pk)[0] + except: + raise PermissionDenied(_('Sem permissão de acesso!')) + + return filterset_class(**kwargs) + + def get_queryset(self): + qs = super().get_queryset() + kwargs = {} + if self.container_field: + kwargs[self.container_field] = self.request.user.pk + + return qs.filter(**kwargs) + + def get_context_data(self, **kwargs): + count = self.object_list.count() + context = super(RelatorioEventoView, + self).get_context_data(**kwargs) + + context['count'] = count + context['title'] = _(self.ctx_title) + + paginator = context['paginator'] + page_obj = context['page_obj'] + + context['page_range'] = make_pagination( + page_obj.number, paginator.num_pages) + + qr = self.request.GET.copy() + if 'page' in qr: + del qr['page'] + context['filter_url'] = ('&' + qr.urlencode()) if len(qr) > 0 else '' + + for agenda in page_obj: + fmt = "%d/%m/%Y às %H:%M" + agenda.inicio = agenda.inicio.strftime(fmt) + agenda.termino = agenda.termino.strftime(fmt) + agenda.url = "/eventos/" + str(agenda.id) + + return context + + def build_pdf(self, response): + + elements = [] + + style = TableStyle([ + ('FONTSIZE', (0, 0), (-1, -1), 8), + ('LEADING', (0, 0), (-1, -1), 7), + #('GRID', (0, 0), (-1, -1), 0.1, colors.black), + #('INNERGRID', (0, 0), (-1, -1), 0.1, colors.black), + ('TOPPADDING', (0, 0), (-1, -1), 3), + ('BOTTOMPADDING', (0, 0), (-1, -1), 3), + ('LEFTPADDING', (0, 0), (-1, -1), 3), + ('RIGHTPADDING', (0, 0), (-1, -1), 3), + ]) + style.add('VALIGN', (0, 0), (-1, -1), 'TOP') + + eventos = Evento.objects.filter(pk__in=self.filterset.form.cleaned_data['pk_selecionados'].split(',')) + + for e in eventos: + data = self.get_data(e) + + for i, value in enumerate(data): + if len(value) <= 1: + style.add('SPAN', (0, i), (-1, i)) + + t = LongTable(data, rowHeights=None, splitByRow=True) + #t = LongTable(data, rowHeights=rowHeights, splitByRow=True) + + t.setStyle(style) + + t._argW[0] = 3 * cm + t._argW[1] = 15 * cm + + elements.append(t) + + elements.append(PageBreak()) + + doc = SimpleDocTemplate( + response, + pagesize=A4, + title=self.relat_title, + rightMargin=1.25 * cm, + leftMargin=1.25 * cm, + topMargin=1.1 * cm, + bottomMargin=0.8 * cm) + + doc.build(elements) + + def get_data(self, processo): + self.set_headings() + self.set_styles() + + cleaned_data = self.filterset.form.cleaned_data + + #where = self.object_list.query.where + + return self.set_body_data(processo) + + def set_headings(self): + self.h_style = getSampleStyleSheet() + self.h3 = self.h_style["Heading3"] + self.h3.fontName = _baseFontNameB + self.h3.alignment = TA_CENTER + + self.h4 = self.h_style["Heading4"] + self.h4.fontName = _baseFontNameB + + self.h5 = self.h_style["Heading5"] + self.h5.fontName = _baseFontNameB + self.h5.alignment = TA_CENTER + + self.h_style = self.h_style["BodyText"] + self.h_style.wordWrap = None # 'LTR' + self.h_style.spaceBefore = 0 + self.h_style.fontSize = 8 + self.h_style.leading = 8 + self.h_style.fontName = _baseFontNameB + + def set_styles(self): + self.s_min = getSampleStyleSheet() + self.s_min = self.s_min["BodyText"] + self.s_min.wordWrap = None # 'LTR' + self.s_min.spaceBefore = 0 + self.s_min.fontSize = 6 + self.s_min.leading = 8 + + self.s_center = getSampleStyleSheet() + self.s_center = self.s_center["BodyText"] + self.s_center.wordWrap = None # 'LTR' + self.s_center.spaceBefore = 0 + self.s_center.alignment = TA_CENTER + self.s_center.fontSize = 8 + self.s_center.leading = 8 + + self.s_left = getSampleStyleSheet() + self.s_left = self.s_left["BodyText"] + self.s_left.wordWrap = None # 'LTR' + self.s_left.spaceBefore = 0 + self.s_left.alignment = TA_LEFT + self.s_left.fontSize = 8 + self.s_left.leading = 8 + + self.s_right = getSampleStyleSheet() + self.s_right = self.s_right["BodyText"] + self.s_right.wordWrap = None # 'LTR' + self.s_right.spaceBefore = 0 + self.s_right.alignment = TA_RIGHT + self.s_right.fontSize = 8 + self.s_right.leading = 8 + + def add_relat_title(self, data): + tit_relatorio = _(self.relat_title) + tit_relatorio = force_text(tit_relatorio) + ' ' + + data.append([Paragraph(tit_relatorio, self.h3)]) + + def build_query(self, contato, where): + p_filter = (('contato_set__' + self.agrupamento, contato),) + if not processo: + p_filter = ( + (p_filter[0][0] + '__isnull', True), + (p_filter[0][0] + '__exact', '') + ) + + q = Q() + for filtro in p_filter: + filtro_dict = {filtro[0]: filtro[1]} + q = q | Q(**filtro_dict) + + eventos_query = Evento.objects.all() + eventos_query.query.where = where.clone() + eventos_query = eventos_query.filter(q) + + params = {self.container_field: self.request.user.pk} + eventos_query = eventos_query.filter(**params) + + eventos_query = eventos_query.order_by( + 'inicio') + return contatos_query + + def set_body_data(self, p): + + legenda = self.h_style + conteudo = self.s_left + + data = [] + + self.add_relat_title(data) + + line = [] + line.append(Paragraph("
", conteudo)) + line.append(Paragraph("
", conteudo)) + data.append(line) + + line = [] + line.append(Paragraph("Título:", legenda)) + line.append(Paragraph(p.titulo, conteudo)) + data.append(line) + + if(p.descricao): + line = [] + line.append(Paragraph("Descrição:", legenda)) + line.append(Paragraph(strip_tags(p.descricao), conteudo)) + data.append(line) + + if(p.localizacao): + line = [] + line.append(Paragraph("Localização:", legenda)) + line.append(Paragraph(strip_tags(p.localizacao), conteudo)) + data.append(line) + + if(p.bairro): + line = [] + line.append(Paragraph("Bairro:", legenda)) + line.append(Paragraph(p.bairro.nome, conteudo)) + data.append(line) + + if(p.municipio): + line = [] + line.append(Paragraph("Município:", legenda)) + line.append(Paragraph(('%s/%s' % (p.municipio.nome, p.estado.sigla)), conteudo)) + data.append(line) + + line = [] + line.append(Paragraph("Início:", legenda)) + line.append(Paragraph(p.inicio.strftime('%d/%m/%Y às %H:%M'), conteudo)) + data.append(line) + + line = [] + line.append(Paragraph("Término:", legenda)) + line.append(Paragraph(p.termino.strftime('%d/%m/%Y às %H:%M'), conteudo)) + data.append(line) + + + return data # # @@ -3237,7 +3527,7 @@ class MalaDiretaView(RelatorioProcessosView): permission_required = 'core.menu_contatos' filterset_class = MalaDiretaFilterSet model = Contato - template_name = 'cerimonial/filter_contatos.html' + template_name = 'cerimonial/filter_contatoemail.html' container_field = 'workspace__operadores' def __init__(self): diff --git a/saap/cerimonial/urls.py b/saap/cerimonial/urls.py index 40bd182..97c637d 100644 --- a/saap/cerimonial/urls.py +++ b/saap/cerimonial/urls.py @@ -3,7 +3,7 @@ from saap.cerimonial.reports import ImpressoEnderecamentoView,\ RelatorioProcessosView, RelatorioContatosView, RelatorioContatosExportaView, \ RelatorioContatoIndividualView, RelatorioProcessoIndividualView, \ - RelatorioAgendaView, MalaDiretaView + RelatorioAgendaView, RelatorioEventoView, MalaDiretaView from saap.cerimonial.views import ContatoCrud, TelefoneCrud, EmailCrud,\ DependenteCrud, LocalTrabalhoCrud, EnderecoCrud, FiliacaoPartidariaCrud,\ EnderecoPerfilCrud, LocalTrabalhoPerfilCrud, EmailPerfilCrud,\ @@ -15,7 +15,7 @@ ContatoFragmentFormPronomesView, StatusProcessoCrud, TopicoProcessoCrud,\ ClassificacaoProcessoCrud, ProcessoMasterCrud, AssuntoProcessoCrud,\ ContatoFragmentFormSearchView, ProcessoContatoCrud,\ - GrupoDeContatosMasterCrud, AgendaView, EventoView \ + GrupoDeContatosMasterCrud, CalendarioView, AniversariosView, EventoCrud \ from .apps import AppConfig @@ -38,14 +38,14 @@ name='ajax_search_contatos'), - url(r'^perfil/', include( - EnderecoPerfilCrud.get_urls() + - LocalTrabalhoPerfilCrud.get_urls() + - EmailPerfilCrud.get_urls() + - TelefonePerfilCrud.get_urls() + - DependentePerfilCrud.get_urls() + - PerfilCrud.get_urls() - )), +# url(r'^perfil/', include( +# EnderecoPerfilCrud.get_urls() + +# LocalTrabalhoPerfilCrud.get_urls() + +# EmailPerfilCrud.get_urls() + +# TelefonePerfilCrud.get_urls() + +# DependentePerfilCrud.get_urls() + +# PerfilCrud.get_urls() +# )), url(r'^grupos/', include( GrupoDeContatosMasterCrud.get_urls() @@ -55,9 +55,10 @@ ProcessoMasterCrud.get_urls() )), - url(r'^agenda/$', AgendaView.as_view(), name='agenda'), - url(r'^evento/$', EventoView.event, name='evento_add'), - url(r'^evento/(?P\d+)/$', EventoView.event, name='evento_edit'), + url(r'^agenda/$', CalendarioView.as_view(), name='agenda'), + url(r'^contatos/aniversarios/$', AniversariosView.as_view(), name='aniversarios'), + + url(r'^eventos/', include(EventoCrud.get_urls())), url(r'^correspondencias/enderecamentos', ImpressoEnderecamentoView.as_view(), @@ -65,7 +66,11 @@ url(r'^relatorios/agenda', RelatorioAgendaView.as_view(), - name='print_agenda'), + name='print_rel_agenda'), + + url(r'^relatorios/evento', + RelatorioEventoView.as_view(), + name='print_evento'), url(r'^relatorios/processos', RelatorioProcessosView.as_view(), diff --git a/saap/cerimonial/utils.py b/saap/cerimonial/utils.py index a49fa11..a945246 100644 --- a/saap/cerimonial/utils.py +++ b/saap/cerimonial/utils.py @@ -1,11 +1,32 @@ from datetime import date, datetime, timedelta from calendar import Calendar, LocaleHTMLCalendar +from pytz import timezone as pytz_timezone +from django.db.models import Q import calendar class Calendar(LocaleHTMLCalendar): - eventos = None + # formats a week as a tr + def formatweek(self, theweek, events): + week = '' + for d, weekday in theweek: + week += self.formatday(d, events) + return f' {week} ' + + # formats a month as a table + # filter events by year and month + def formatmonth(self, withyear=True): + + cal = f'\n' + cal += f'{self.formatmonthname(self.year, self.month, withyear=withyear)}\n' + cal += f'{self.formatweekheader()}\n' + for week in self.monthdays2calendar(self.year, self.month): + cal += f'{self.formatweek(week, self.events)}\n' + cal += f'
' + return cal + +class CalendarAgenda(Calendar): def __init__(self, year=None, month=None, events=None, locale='pt_BR.UTF-8'): self.year = year @@ -17,39 +38,174 @@ def __init__(self, year=None, month=None, events=None, locale='pt_BR.UTF-8'): # formats a day as a td # filter events by day def formatday(self, day, events): + + hoje = date.today() + + if(self.year < hoje.year): + estilo_passado = 'passado' + elif(self.year == hoje.year and self.month < hoje.month): + estilo_passado = 'passado' + elif(self.year == hoje.year and self.month == hoje.month and day < hoje.day): + estilo_passado = 'passado' + else: + estilo_passado = '' + + if(hoje.day == day and hoje.month == self.month and hoje.year == self.year): + estilo_hoje = 'hoje' + else: + estilo_hoje = '' + events_per_day = events.filter(inicio__day=day) d = '' for event in events_per_day: - d += f'{event.get_html_url}
' + + inicio_concomitante = events.filter(inicio__lte=event.inicio, termino__gte=event.inicio) + inicio_concomitante = inicio_concomitante.filter(~Q(pk=event.pk)) + + termino_concomitante = events.filter(inicio__lte=event.termino, termino__gte=event.termino) + termino_concomitante = termino_concomitante.filter(~Q(pk=event.pk)) + + concomitante = '' + if (inicio_concomitante.count() > 0 or termino_concomitante.count() > 0): + concomitante = 'evento-concomitante' + + url = "/eventos/" + str(event.pk) + fmt = "%d/%m/%Y às %H:%M" + event.inicio = event.inicio.astimezone(pytz_timezone('America/Sao_Paulo')) + event.termino = event.termino.astimezone(pytz_timezone('America/Sao_Paulo')) + + longo = '' + qtde_dias = 0 + if (event.termino.day != event.inicio.day): + longo = 'evento-longo' + qtde_dias = (event.termino.day - event.inicio.day) + + if(event.bairro != None): + str_bairro = event.bairro.nome + else: + str_bairro = '' + + if(event.municipio != None): + str_municipio = event.municipio.nome + else: + str_municipio = '' + + text = "Descrição: " + event.descricao + "\n\n" + \ + "Local: " + event.localizacao + "\n" + \ + "Bairro: " + str_bairro + "\n" + \ + "Município: " + str_municipio + "\n\n" + \ + "Início: " + event.inicio.strftime(fmt) + "\n" + \ + "Término: " + event.termino.strftime(fmt) + hora_inicio = event.inicio.strftime("%H:%M") + hora_termino = event.termino.strftime("%H:%M") + + dias_duracao = "" + if(qtde_dias > 0): + dias_duracao = "(+" + str(qtde_dias) + ")" + + evento_formatado = f' {hora_inicio}-{hora_termino}{dias_duracao} {event.titulo}' + d += f'{evento_formatado}
' if day != 0: - return f"{day}
{d}" + return f"{day}
{d}" return '' - # formats a week as a tr - def formatweek(self, theweek, events): - week = '' - for d, weekday in theweek: - week += self.formatday(d, events) - return f' {week} ' +class CalendarAniversarios(Calendar): + + def __init__(self, year=None, month=None, birthdays=None, locale='pt_BR.UTF-8'): + self.year = year + self.month = month + super(Calendar, self).__init__() + self.setfirstweekday(6) + self.events = birthdays + + # formats a day as a td + # filter birthdays by day + def formatday(self, day, events): + + hoje = date.today() + + if(self.year < hoje.year): + estilo_passado = 'passado' + elif(self.year == hoje.year and self.month < hoje.month): + estilo_passado = 'passado' + elif(self.year == hoje.year and self.month == hoje.month and day < hoje.day): + estilo_passado = 'passado' + else: + estilo_passado = '' + + if(hoje.day == day and hoje.month == self.month and hoje.year == self.year): + estilo_hoje = 'hoje' + else: + estilo_hoje = '' + + #birthdays_per_day = events.filter(data_nascimento__day=day) + d = '' + for birthday in events: + if(birthday.data_nascimento != None): + if(birthday.data_nascimento.day == day): + url = "/contatos/" + str(birthday.pk) + idade = self.year - birthday.data_nascimento.year + + nascimento = str(birthday.data_nascimento.strftime("%d/%m/%Y")) + + enderecos = birthday.endereco_set.all() + endereco_texto = '' + municipio_texto = '' + for endereco in enderecos: + if(endereco.permite_contato == True): + endereco_texto = endereco.endereco + if(endereco.numero == None): + endereco_texto += ", S/N" + else: + if(endereco.numero > 0): + endereco_texto += ", " + str(endereco.numero) + else: + endereco_texto += ", S/N" + + if(endereco.complemento != '' and endereco.complemento != None): + endereco_texto += " - " + endereco.complemento + + endereco_texto += ' - %s' % endereco.bairro.nome if endereco.bairro else '' + + municipio_texto = '%s/%s' % (endereco.municipio.nome, endereco.estado.sigla) + + break + + telefones = birthday.telefone_set.all() + telefone_texto = '' + for telefone in telefones: + if(telefone.permite_contato == True): + telefone_texto += telefone.telefone + break + + emails = birthday.email_set.all() + email_texto = '' + for email in emails: + if(email.permite_contato == True): + email_texto += email.email + break + + text = "Nome: " + birthday.nome + "\n" \ + "Data de nascimento: " + nascimento + "\n\n" \ + "Endereço: " + endereco_texto + "\n" \ + "Município: " + municipio_texto + "\n\n" \ + "Telefone: " + telefone_texto + "\n\n" \ + "E-mail: " + email_texto + + birthday_formatted = f' {idade} - {birthday.nome}' + d += f'{birthday_formatted}
' + + if day != 0: + return f"{day}
{d}" + return '' - # formats a month as a table - # filter events by year and month - def formatmonth(self, withyear=True): - - cal = f'\n' - cal += f'{self.formatmonthname(self.year, self.month, withyear=withyear)}\n' - cal += f'{self.formatweekheader()}\n' - for week in self.monthdays2calendar(self.year, self.month): - cal += f'{self.formatweek(week, self.events)}\n' - cal += f'
' - return cal def get_date(req_day): if req_day: year, month = (int(x) for x in req_day.split('-')) return date(year, month, day=1) - return datetime.today() + return date.today() def prev_month(d): first = d.replace(day=1) diff --git a/saap/cerimonial/views.py b/saap/cerimonial/views.py index 5fa16ff..9d11767 100644 --- a/saap/cerimonial/views.py +++ b/saap/cerimonial/views.py @@ -1,17 +1,15 @@ from django.core.exceptions import PermissionDenied from django.db.models.aggregates import Max -from django.db.models import Q +from django.db.models import Q, F, Func, Value from django.utils.translation import ugettext_lazy as _ from django.views.generic.edit import FormView from django.utils.safestring import mark_safe -from django.shortcuts import render, get_object_or_404 +from django.shortcuts import render from django.views import generic -from django.http import HttpResponseRedirect -from django.core.urlresolvers import reverse from _functools import reduce -from datetime import date, timedelta +from datetime import date, timedelta, datetime import datetime import operator @@ -32,7 +30,8 @@ AssuntoProcesso, ProcessoContato, GrupoDeContatos, Evento from saap.cerimonial.rules import rules_patterns -from saap.cerimonial.utils import Calendar, get_date, prev_month, prev_year, next_month, next_year, this_month +from saap.cerimonial.utils import CalendarAgenda, CalendarAniversarios, \ + get_date, prev_month, prev_year, next_month, next_year, this_month from saap.utils import normalize @@ -44,9 +43,6 @@ from saap.globalrules.crud_custom import DetailMasterCrud,\ MasterDetailCrudPermission, PerfilAbstractCrud, PerfilDetailCrudPermission -# Variável usada para transportar a area de trabalho na seção de agenda/evento -workspace = None - globalrules.rules.config_groups(rules_patterns) # ---- Details Master Crud build --------------------------- @@ -409,21 +405,19 @@ def post(self, request, *args, **kwargs): # pk=self.object.pk).update(preferencial=False) return response -class AgendaView(generic.ListView): +class CalendarioView(generic.ListView): model = Evento - template_name = 'cerimonial/agenda.html' + template_name = 'cerimonial/calendario.html' def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context['title'] = "Agenda" d = get_date(self.request.GET.get('mes', None)) - - global workspace workspace = AreaTrabalho.objects.filter(operadores=self.request.user.pk)[0] eventos = Evento.objects.filter(inicio__year=d.year, inicio__month=d.month, workspace=workspace).order_by('inicio') - cal = Calendar(d.year, d.month, eventos) + cal = CalendarAgenda(d.year, d.month, eventos) # Call the formatmonth method, which returns our calendar as a table html_cal = cal.formatmonth(withyear=True) @@ -435,26 +429,78 @@ def get_context_data(self, **kwargs): context['this_month'] = this_month() return context -class EventoView(): +class AniversariosView(generic.ListView): + model = Contato + template_name = 'cerimonial/aniversarios.html' + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context['title'] = "Aniversários" + + d = get_date(self.request.GET.get('mes', None)) + + workspace = AreaTrabalho.objects.filter(operadores=self.request.user.pk)[0] + contatos = Contato.objects.prefetch_related('email_set', 'telefone_set', 'endereco_set', 'endereco_set__estado', 'endereco_set__municipio', 'endereco_set__bairro').filter( data_nascimento__month=d.month, workspace=workspace).order_by('data_nascimento') + cal = CalendarAniversarios(d.year, d.month, contatos) + + # Call the formatmonth method, which returns our calendar as a table + html_cal = cal.formatmonth(withyear=True) + context['calendar'] = mark_safe(html_cal) + context['prev_month'] = prev_month(d) + context['next_month'] = next_month(d) + context['prev_year'] = prev_year(d) + context['next_year'] = next_year(d) + context['this_month'] = this_month() + return context + + + +class EventoCrud(DetailMasterCrud): + model = Evento + container_field_set = 'workspace__operadores' + + class BaseMixin(DetailMasterCrud.BaseMixin): + list_field_names = ['titulo', ('bairro', 'municipio'), 'inicio', 'termino'] + layout_key = 'Evento' + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context['subnav_template_name'] = None + return context + + def get_initial(self): + initial = {} + + try: + initial['workspace'] = AreaTrabalho.objects.filter( + operadores=self.request.user.pk)[0] + except: + raise PermissionDenied(_('Sem permissão de acesso!')) + + return initial - def event(request, event_id=None): - global workspace - instance = Evento() - if event_id: - instance = get_object_or_404(Evento, pk=event_id) - else: - instance = Evento() - - form = EventoForm(request.POST or None, instance=instance, workspace=workspace) - if request.POST and form.is_valid(): - inicio = form.cleaned_data['inicio'] - #month = "mes=" + str(inicio.year) + "-" + str(inicio.month) - form.save() - #return HttpResponseRedirect(reverse('saap.cerimonial:agenda_mes', args=(month,))) - return HttpResponseRedirect(reverse('saap.cerimonial:agenda')) - return render(request, 'cerimonial/evento.html', {'form': form, 'title': "Evento"}) + class ListView(DetailMasterCrud.ListView): + def get(self, request, *args, **kwargs): + return DetailMasterCrud.ListView.get( + self, request, *args, **kwargs) + + def get_queryset(self): + queryset = DetailMasterCrud.ListView.get_queryset(self) + + queryset = queryset.filter(workspace=AreaTrabalho.objects.filter(operadores=self.request.user.pk)[0]) + queryset = queryset.order_by('inicio') + + return queryset + + class CreateView(DetailMasterCrud.CreateView): + form_class = EventoForm + layout_key = 'Evento' + + class UpdateView(DetailMasterCrud.UpdateView): + form_class = EventoForm + layout_key = 'Evento' class FiliacaoPartidariaCrud(MasterDetailCrudPermission): model = FiliacaoPartidaria @@ -566,8 +612,7 @@ class EnderecoPerfilCrud(PerfilDetailCrudPermission): parent_field = 'contato' class BaseMixin(PerfilDetailCrudPermission.BaseMixin): - #list_field_names = [('endereco', 'numero'), 'cep', 'bairro','municipio', 'principal', 'permite_contato'] - list_field_names = ['endereco', 'numero', 'cep', 'bairro','municipio', 'principal', 'permite_contato'] + list_field_names = [('endereco', 'numero'), 'cep', 'bairro','municipio', 'principal', 'permite_contato'] class CreateView(PrincipalMixin, PerfilDetailCrudPermission.CreateView): form_class = EnderecoForm @@ -657,7 +702,8 @@ class BaseMixin(DetailMasterCrud.BaseMixin): def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) - context['subnav_template_name'] = 'cerimonial/subnav_processo.yaml' + #context['subnav_template_name'] = 'cerimonial/subnav_processo.yaml' + context['subnav_template_name'] = None return context def get_form(self, form_class=None): diff --git a/saap/core/admin.py b/saap/core/admin.py index 54de2e8..d79aed5 100644 --- a/saap/core/admin.py +++ b/saap/core/admin.py @@ -6,6 +6,8 @@ from saap.utils import register_all_models_in_admin +from saap.core.models import AuditLog + from .forms import UserChangeForm, UserCreationForm from .models import User @@ -55,3 +57,32 @@ class ParlamentarAdmin(admin.ModelAdmin): #admin.site.register(get_user_model(), ParlamentarAdmin) register_all_models_in_admin(__name__) + +class AuditLogAdmin(admin.ModelAdmin): + pass + + def has_add_permission(self, request): + return False + + # def has_change_permission(self, request, obj=None): + # return False + # + def has_delete_permission(self, request, obj=None): + return False + + def save_model(self, request, obj, form, change): + pass + + def delete_model(self, request, obj): + pass + + def save_related(self, request, form, formsets, change): + pass + + +# Na linha acima register_all_models_in_admin registrou AuditLog +admin.site.unregister(AuditLog) +admin.site.register(AuditLog, AuditLogAdmin) + +admin.site.site_title = 'Administração - SAAP' +admin.site.site_header = 'Administração - SAAP' diff --git a/saap/core/apps.py b/saap/core/apps.py index d693058..8f7e9f4 100644 --- a/saap/core/apps.py +++ b/saap/core/apps.py @@ -6,3 +6,6 @@ class AppConfig(apps.AppConfig): name = 'saap.core' label = 'core' verbose_name = _('Ajustes principais') + + def ready(self): + from saap.core import receivers diff --git a/saap/core/migrations/0033_auditlog.py b/saap/core/migrations/0033_auditlog.py new file mode 100644 index 0000000..91cfb32 --- /dev/null +++ b/saap/core/migrations/0033_auditlog.py @@ -0,0 +1,33 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.13 on 2022-05-31 13:26 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0032_auto_20220518_1534'), + ] + + operations = [ + migrations.CreateModel( + name='AuditLog', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('username', models.CharField(blank=True, db_index=True, max_length=100, verbose_name='username')), + ('operation', models.CharField(db_index=True, max_length=1, verbose_name='operation')), + ('timestamp', models.DateTimeField(db_index=True, verbose_name='timestamp')), + ('object', models.CharField(blank=True, max_length=4096, verbose_name='object')), + ('object_id', models.PositiveIntegerField(db_index=True, verbose_name='object_id')), + ('model_name', models.CharField(db_index=True, max_length=100, verbose_name='model')), + ('app_name', models.CharField(db_index=True, max_length=100, verbose_name='app')), + ], + options={ + 'verbose_name': 'AuditLog', + 'verbose_name_plural': 'AuditLogs', + 'ordering': ('-id',), + }, + ), + ] diff --git a/saap/core/models.py b/saap/core/models.py index 3c6f846..888f5ea 100644 --- a/saap/core/models.py +++ b/saap/core/models.py @@ -882,3 +882,43 @@ def __str__(self): return _('%(parlamentar)s - %(partido)s') % { 'parlamentar': self.parlamentar, 'partido': self.partido } + + +class AuditLog(models.Model): + + operation = ('C', 'D', 'U') + + MAX_DATA_LENGTH = 4096 # 4KB de texto + + username = models.CharField(max_length=100, + verbose_name=_('username'), + blank=True, + db_index=True) + operation = models.CharField(max_length=1, + verbose_name=_('operation'), + db_index=True) + timestamp = models.DateTimeField(verbose_name=_('timestamp'), + db_index=True) + object = models.CharField(max_length=MAX_DATA_LENGTH, + blank=True, + verbose_name=_('object')) + object_id = models.PositiveIntegerField(verbose_name=_('object_id'), + db_index=True) + model_name = models.CharField(max_length=100, verbose_name=_('model'), + db_index=True) + app_name = models.CharField(max_length=100, + verbose_name=_('app'), + db_index=True) + + class Meta: + verbose_name = _('AuditLog') + verbose_name_plural = _('AuditLogs') + ordering = ('-id',) + + def __str__(self): + return "[%s] %s %s.%s %s" % (self.timestamp, + self.operation, + self.app_name, + self.model_name, + self.username, + ) diff --git a/saap/core/receivers.py b/saap/core/receivers.py new file mode 100644 index 0000000..134d9f2 --- /dev/null +++ b/saap/core/receivers.py @@ -0,0 +1,78 @@ +import inspect +import logging + +from django.conf import settings +from django.contrib.contenttypes.models import ContentType +from django.core import serializers +from django.db.models.signals import post_delete, post_save, \ + post_migrate +from django.db.utils import DEFAULT_DB_ALIAS +from django.dispatch import receiver +from django.utils import timezone +from django.utils.translation import ugettext_lazy as _ + +from saap.core.models import AuditLog + +def audit_log_function(sender, **kwargs): + try: + if not (sender._meta.app_config.name.startswith('saap') or + sender._meta.label == settings.AUTH_USER_MODEL): + return + except: + # não é necessário usar logger, aqui é usada apenas para + # eliminar um o if complexo + return + + instance = kwargs.get('instance') + if instance._meta.model == AuditLog: + return + + logger = logging.getLogger(__name__) + + u = None + pilha_de_execucao = inspect.stack() + for i in pilha_de_execucao: + if i.function == 'migrate': + return + r = i.frame.f_locals.get('request', None) + try: + if r.user._meta.label == settings.AUTH_USER_MODEL: + u = r.user + break + except: + # não é necessário usar logger, aqui é usada apenas para + # eliminar um o if complexo + pass + + operation = kwargs.get('operation') + user = u + model_name = instance.__class__.__name__ + app_name = instance._meta.app_label + object_id = instance.id + data = serializers.serialize('json', [instance]) + + if len(data) > AuditLog.MAX_DATA_LENGTH: + data = data[:AuditLog.MAX_DATA_LENGTH] + + if user: + username = user + else: + username = '' + + AuditLog.objects.create(username=username, + operation=operation, + model_name=model_name, + app_name=app_name, + timestamp=timezone.now(), + object_id=object_id, + object=data) + +@receiver(post_delete) +def audit_log_post_delete(sender, **kwargs): + audit_log_function(sender, operation='D', **kwargs) + + +@receiver(post_save) +def audit_log_post_save(sender, **kwargs): + operation = 'C' if kwargs.get('created') else 'U' + audit_log_function(sender, operation=operation, **kwargs) diff --git a/saap/settings.py b/saap/settings.py index 9e0dda6..8440153 100644 --- a/saap/settings.py +++ b/saap/settings.py @@ -57,11 +57,11 @@ DADOS_SITE = config('DADOS_SITE'); BRASAO_PROPRIO = config('BRASAO_PROPRIO'); -VERSION='3.1.1' +VERSION='3.1.2' INSTALLED_APPS = ( - #'django_admin_bootstrapped', - 'bootstrap_admin', + 'django_admin_bootstrapped', + #'bootstrap_admin', 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', @@ -73,7 +73,7 @@ #'social_django', # more -# 'import_export', + #'import_export', 'smart_selects', 'django_extensions', 'djangobower', @@ -91,7 +91,7 @@ 'debug_toolbar', 'taggit', 'modelcluster', - 'easyaudit', +# 'easyaudit', ) INSTALLED_APPS = INSTALLED_APPS + SAAP_APPS @@ -111,7 +111,7 @@ 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', 'django.middleware.security.SecurityMiddleware', - 'easyaudit.middleware.easyaudit.EasyAuditMiddleware', +# 'easyaudit.middleware.easyaudit.EasyAuditMiddleware', ) if DEBUG: diff --git a/saap/static/styles/app.css b/saap/static/styles/app.css index 63f7353..21b2e27 100644 --- a/saap/static/styles/app.css +++ b/saap/static/styles/app.css @@ -1284,6 +1284,14 @@ nav .dropdown-menu > li > a { font-weight: bold; } +.calendario .hoje { + background: #d6e1e5; +} + +.calendario .passado { + background: #b9b9b9; +} + .left { float: left; } @@ -1314,3 +1322,15 @@ nav .dropdown-menu > li > a { .evento .form-control { margin-bottom: 10px; } + +.evento-longo { + color: #cc0c0c; +} + +.evento-concomitante { + color: #1919ec; +} + +.evento-passado { + color: #a0a0a0; +} diff --git a/saap/templates/base.html b/saap/templates/base.html index 261237c..4fe720f 100644 --- a/saap/templates/base.html +++ b/saap/templates/base.html @@ -98,7 +98,16 @@ {# if perms.core.menu_agenda #} {% if perms.core.menu_contatos %} {# Permissão temporária. Criar no futuro #} -
  • {% trans "Agenda" %}
  • +
  • + + {% endif %} {# if perms.core.menu_correspondencias #} @@ -107,7 +116,7 @@ {% trans "Correspondências" %}
  • {% endif %} diff --git a/saap/templates/cerimonial/aniversarios.html b/saap/templates/cerimonial/aniversarios.html new file mode 100644 index 0000000..871c4ea --- /dev/null +++ b/saap/templates/cerimonial/aniversarios.html @@ -0,0 +1,20 @@ +{% extends "base.html" %} +{% load i18n crispy_forms_tags common_tags %} + +{% block base_content %} + +
    + + +
    O número à direita do Contato representa quantos anos o mesmo está completando naquele dia, mês e ano. + {{ calendar }} + +
    + +{% endblock %} diff --git a/saap/templates/cerimonial/agenda.html b/saap/templates/cerimonial/calendario.html similarity index 69% rename from saap/templates/cerimonial/agenda.html rename to saap/templates/cerimonial/calendario.html index ed0ec4c..662c501 100644 --- a/saap/templates/cerimonial/agenda.html +++ b/saap/templates/cerimonial/calendario.html @@ -11,8 +11,12 @@ Mês atual Próximo mês Próximo ano - Novo evento + Adicionar evento +
    + Eventos que não terminam no mesmo dia possuem a informação da duração destacada em vermelho após o horário. +
    + Eventos que possuem horário simultâneo a outros estão destacados em azul. {{ calendar }} diff --git a/saap/templates/cerimonial/evento.html b/saap/templates/cerimonial/evento.html deleted file mode 100644 index 0d83e6c..0000000 --- a/saap/templates/cerimonial/evento.html +++ /dev/null @@ -1,37 +0,0 @@ -{% extends "base.html" %} -{% load i18n crispy_forms_tags common_tags %} - -{% block base_content %} - -{% if form.errors %} - {% for field in form %} - {% for error in field.errors %} -
    - Campo {{ field.label }} inválido!
    {{ error|escape }} -
    - {% endfor %} - {% endfor %} - {% for error in form.non_field_errors %} -
    - Campo {{ field.label }} inválido!
    {{ error|escape }} -
    - {% endfor %} -{% endif %} - -
    - {% csrf_token %} - - - {{ form }} - -
    - Voltar - -
    -
    -{% endblock %} - -{% block extra_js %} - - -{% endblock %} diff --git a/saap/templates/cerimonial/filter_contatoemail.html b/saap/templates/cerimonial/filter_contatoemail.html new file mode 100644 index 0000000..e3a1eed --- /dev/null +++ b/saap/templates/cerimonial/filter_contatoemail.html @@ -0,0 +1,77 @@ +{% extends "base.html" %} +{% load i18n common_tags crispy_forms_tags%} + +{% block base_content %} +
    + {% if filter.form %} + {% crispy filter.form %} + {% endif %} +
    + {% block extra_content %} {% endblock %} + Obs.: Contatos que não possuem e-mail cadastrado e marcado como para contato possuem seu nome destacado em vermelho. +

    + +
    +
    {% blocktrans with verbose_name_plural=view.verbose_name_plural %}Total de {{ verbose_name_plural }} selecionados: {{count}}{% endblocktrans %}
    + + + + + + + + + + + + + + {% for obj in page_obj %} + + + {% if obj.email == '' %} + + {% else %} + + {% endif %} + + + + + + + {% endfor %} + +
    Código
    NomeE-mail para contatoBairroMunicípioTelefoneGrupo
    +
    {{ obj.pk|safe }}
    +
    {{ obj.nome|safe }}{{ obj.nome|safe }} + {{ obj.email|safe }} + + {{ obj.bairro|safe }} + + {{ obj.municipio|safe }} + + {{ obj.telefone|safe }} + + {% for grupo in obj.grupodecontatos_set.all%} + {% if forloop.first %} +
      + {% endif %} +
    • {{grupo.nome}}
    • + {% if forloop.last %} +
    + {% endif %} + {% endfor %} + {{ obj.grupocontato_set.all}} +
    +
    + {% include "paginacao.html" %} +{% endblock %} + +{% block extra_js %} + +{% endblock %} diff --git a/saap/templates/cerimonial/filter_contatos.html b/saap/templates/cerimonial/filter_contatos.html index f549824..86080ea 100644 --- a/saap/templates/cerimonial/filter_contatos.html +++ b/saap/templates/cerimonial/filter_contatos.html @@ -8,6 +8,7 @@ {% endif %} {% block extra_content %} {% endblock %} +
    {% blocktrans with verbose_name_plural=view.verbose_name_plural %}Total de {{ verbose_name_plural }} selecionados: {{count}}{% endblocktrans %}
    @@ -28,11 +29,9 @@ - {% if obj.email == '' %} - - {% else %} - - {% endif %} + diff --git a/saap/templates/cerimonial/filter_evento.html b/saap/templates/cerimonial/filter_evento.html new file mode 100644 index 0000000..52e3e74 --- /dev/null +++ b/saap/templates/cerimonial/filter_evento.html @@ -0,0 +1,102 @@ +{% extends "base.html" %} +{% load i18n common_tags crispy_forms_tags%} + +{% block base_content %} +
    + {% if filter.form %} + {% crispy filter.form %} + {% endif %} +
    + {% block extra_content %} {% endblock %} +
    +
    {% blocktrans with verbose_name_plural=view.verbose_name_plural %}{{ verbose_name_plural }} encontrados: {{count}}{% endblocktrans %}
    + +
    {{ obj.pk|safe }}
    {{ obj.nome|safe }}{{ obj.nome|safe }} + {{ obj.nome|safe }} + {{ obj.email|safe }}
    + + + + + + + + + + + + + {% for obj in page_obj %} + + + + + + + + + + {% endfor %} + +
    CódigoTítuloDescriçãoMunicípioInícioTérmino
    + + + {{ obj.pk|safe }} + + {{ obj.titulo|safe }} + + {{ obj.descricao|safe }} + + {% if obj.municipio != None %} + {{ obj.municipio }} + {% else %} + - + {% endif %} + + {{ obj.inicio|safe }} + + {{ obj.termino|safe }} +
    +
    + {% include "paginacao.html" %} +{% endblock %} + +{% block extra_js %} + +{% endblock %} diff --git a/saap/templates/cerimonial/filter_impressoenderecamento_contato.html b/saap/templates/cerimonial/filter_impressoenderecamento_contato.html index 4029f07..f767ef4 100644 --- a/saap/templates/cerimonial/filter_impressoenderecamento_contato.html +++ b/saap/templates/cerimonial/filter_impressoenderecamento_contato.html @@ -8,6 +8,9 @@ {% endif %} {% block extra_content %} {% endblock %} + Obs.: Contatos que não possuem endereço cadastrado e marcado como para contato possuem seu nome destacado em vermelho. +

    +
    {% blocktrans with verbose_name_plural=view.verbose_name_plural %}Total de {{ verbose_name_plural }} selecionados: {{count}}{% endblocktrans %}
    diff --git a/saap/templates/cerimonial/layouts.yaml b/saap/templates/cerimonial/layouts.yaml index ffaebbd..559f6bb 100644 --- a/saap/templates/cerimonial/layouts.yaml +++ b/saap/templates/cerimonial/layouts.yaml @@ -219,3 +219,10 @@ ProcessoLayoutForForm: GrupoDeContatosLayoutForForm: {% trans 'Dados básicos' %}: - nome +Evento: + {% trans 'Evento' %}: + - titulo + - descricao + - localizacao + - estado municipio bairro + - inicio termino diff --git a/saap/templates/home/home_page.html b/saap/templates/home/home_page.html deleted file mode 100644 index 02ef8e0..0000000 --- a/saap/templates/home/home_page.html +++ /dev/null @@ -1,14 +0,0 @@ -{% extends "base.html" %} - -{% block body_class %}homepage{% endblock %} - -{% block base_content %} - -Você está acessando a nova ferramenta da Câmara Municipal de Jataí, que será a plataforma para as soluções parlamentares, legislativas, administrativas, transparência e institucionais. Soluções estas que serão migradas possivelmente na ordem citada, respectivamente. -

    -Inicialmente, em fase final de migração, a solução de apoio aos Parlamentares.

    -Se você é um funcionário de gabinete, use a opção Acessar e faça autenticação com seu Facebook ou sua conta do Google e, em seguida, solicite ao Departamento de Informática que lhe dê permissão de acesso ao seu Gabinete Parlamentar. -
    Se você não é funcionário da Câmara, no futuro teremos funcionalidades para sua interação dentro do Portal, coisas como solicitações, comentários, edição participativa de matérias e outros. -

    Observamos que a autenticação está disponivel apenas via Facebook e/ou Google por ser um meio seguro de autenticação. Criar algo próprio da Câmara Municipal de Jataí com segurança mínima e, ainda assim, menor do que as oferecidas já citadas, seria um tempo gasto com uma burocracia desnecessária, ao menos na atualidade! - -{% endblock %} diff --git a/saap/templates/relatorios.html b/saap/templates/relatorios.html index 22f7d39..0ed8a83 100644 --- a/saap/templates/relatorios.html +++ b/saap/templates/relatorios.html @@ -18,7 +18,7 @@

    Contatos

    - + @@ -34,7 +34,7 @@

    Processos

    - + @@ -47,10 +47,13 @@

    Agenda

    Lista completa de contatos, em PDF, contendo algumas informações.
    {% trans "Dados detalhados" %}{% trans "Detalhamento" %} Ficha completa, com todos os dados de um contato.
    Lista completa de processos, em PDF, contendo algumas informações.
    {% trans "Dados detalhados" %}{% trans "Detalhamento" %} Ficha completa, com todos os dados de um processo.
    - - + + + + +
    {% trans "Listagem" %}{% trans "Listagem" %} Lista completa de eventos e compromissos, em PDF.
    {% trans "Detalhamento" %} Ficha completa, com todos os dados de um evento.
    {% endif %} diff --git a/saap/urls.py b/saap/urls.py index 72d650d..9cab038 100644 --- a/saap/urls.py +++ b/saap/urls.py @@ -25,9 +25,9 @@ urlpatterns = [ url(r'^$', TemplateView.as_view(template_name='index.html')), - url(r'^django-admin/', admin.site.urls), + #url(r'^django-admin/', admin.site.urls), - url('', include('social.apps.django_app.urls', namespace='social')), + #url('', include('social.apps.django_app.urls', namespace='social')), url(r'', include(saap.core.urls)), url(r'', include(saap.cerimonial.urls)), From 48555180c5c1ee49aff4bbae09289d84ef3fdf87 Mon Sep 17 00:00:00 2001 From: Jonatha Cardoso Date: Wed, 8 Jun 2022 10:39:19 -0300 Subject: [PATCH 2/7] Update settings.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Correção para testar se o Debug Toolbar está instalado ou não, para fazer a sua importação --- saap/settings.py | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/saap/settings.py b/saap/settings.py index 8440153..15e8e91 100644 --- a/saap/settings.py +++ b/saap/settings.py @@ -61,7 +61,6 @@ INSTALLED_APPS = ( 'django_admin_bootstrapped', - #'bootstrap_admin', 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', @@ -88,19 +87,12 @@ # 'haystack', # "elasticstack", - 'debug_toolbar', 'taggit', 'modelcluster', -# 'easyaudit', ) INSTALLED_APPS = INSTALLED_APPS + SAAP_APPS - -# if DEBUG and 'debug_toolbar' not in INSTALLED_APPS: -# INSTALLED_APPS += ('debug_toolbar',) - - MIDDLEWARE_CLASSES = ( 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.locale.LocaleMiddleware', @@ -111,14 +103,19 @@ 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', 'django.middleware.security.SecurityMiddleware', -# 'easyaudit.middleware.easyaudit.EasyAuditMiddleware', ) +try: + import debug_toolbar + MIDDLEWARE_CLASSES += ( + 'debug_toolbar.middleware.DebugToolbarMiddleware', + ) + INSTALLED_APPS += ('debug_toolbar',) +except ImportError: + pass + if DEBUG: INTERNAL_IPS = ('127.0.0.1', 'localhost', '172.27.80.68') - MIDDLEWARE_CLASSES += ( - 'debug_toolbar.middleware.DebugToolbarMiddleware', - ) DEBUG_TOOLBAR_PANELS = [ 'debug_toolbar.panels.versions.VersionsPanel', From 55890cb14991a256b7c4f5c066eeb904cb86271c Mon Sep 17 00:00:00 2001 From: Jonatha Cardoso Date: Wed, 8 Jun 2022 11:04:09 -0300 Subject: [PATCH 3/7] Update urls.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Correção para testar se o Debug Toolbar está instalado ou não, para fazer a sua importação --- saap/urls.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/saap/urls.py b/saap/urls.py index 9cab038..3b45251 100644 --- a/saap/urls.py +++ b/saap/urls.py @@ -51,7 +51,10 @@ }), ] - import debug_toolbar - urlpatterns += [ - url(r'^__debug__/', include(debug_toolbar.urls)), - ] + try: + import debug_toolbar + urlpatterns += [ + url(r'^__debug__/', include(debug_toolbar.urls)), + ] + except ImportError: + pass From 99af2fb5ed7d82e0fc74f83c5c2a0aa8a81d16c3 Mon Sep 17 00:00:00 2001 From: Jonatha Cardoso Date: Wed, 8 Jun 2022 11:28:54 -0300 Subject: [PATCH 4/7] Update start.sh MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Correção na criação da extensão unaccent e remoção da exibição do usuário --- docker/start.sh | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/docker/start.sh b/docker/start.sh index a70b272..534403c 100644 --- a/docker/start.sh +++ b/docker/start.sh @@ -56,7 +56,7 @@ load_db() { yes yes | python3 manage.py migrate echo "[LOAD_DB] Creating extension..." - psql -h saapdb -c "CREATE EXTENSION unaccent;" + psql -h saapdb -U saap -c "CREATE EXTENSION unaccent;" echo "[LOAD_DB] Done!" } @@ -67,8 +67,6 @@ create_superuser(){ user_created=$(python3 create_admin.py 2>&1) - echo $user_created - cmd=$(echo $user_created | grep 'ADMIN_USER_EXISTS') user_exists=$? From a4f8482aac37248f0df547bd279c3d437bc468a9 Mon Sep 17 00:00:00 2001 From: Jonatha Cardoso Date: Wed, 8 Jun 2022 11:45:47 -0300 Subject: [PATCH 5/7] Update django_content_type.sql MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Troca dos espaços por tabulação para correta importação --- config/initial_data/django_content_type.sql | 128 ++++++++++---------- 1 file changed, 65 insertions(+), 63 deletions(-) diff --git a/config/initial_data/django_content_type.sql b/config/initial_data/django_content_type.sql index 3c9d256..2d059d9 100644 --- a/config/initial_data/django_content_type.sql +++ b/config/initial_data/django_content_type.sql @@ -19,71 +19,73 @@ DELETE FROM public.django_admin_log; DELETE FROM public.django_content_type; COPY public.django_content_type (id, app_label, model) FROM stdin; -1 admin logentry -2 auth permission -3 auth group -4 contenttypes contenttype -5 sessions session -6 easy_thumbnails source -7 easy_thumbnails thumbnail -8 easy_thumbnails thumbnaildimensions -9 taggit tag -10 taggit taggeditem -11 core user -12 core municipio -13 core nivelinstrucao -14 core situacaomilitar -15 core parlamentar -16 core partido -17 core areatrabalho -18 core operadorareatrabalho -19 core cep -20 core regiaomunicipal -21 core distrito -22 core bairro -23 core tipologradouro -24 core logradouro -25 core trecho -26 core impressoenderecamento -27 core filiacao -28 cerimonial tipotelefone -29 cerimonial tipoendereco -30 cerimonial tipoemail -31 cerimonial parentesco -32 cerimonial estadocivil -33 cerimonial pronometratamento -34 cerimonial tipoautoridade -35 cerimonial tipolocaltrabalho -36 cerimonial nivelinstrucao -37 cerimonial operadoratelefonia -38 cerimonial contato -39 cerimonial perfil -40 cerimonial telefone -41 cerimonial telefoneperfil -42 cerimonial email -43 cerimonial emailperfil -44 cerimonial dependente -45 cerimonial dependenteperfil -46 cerimonial localtrabalho -47 cerimonial localtrabalhoperfil -48 cerimonial endereco -49 cerimonial enderecoperfil -50 cerimonial filiacaopartidaria -51 cerimonial statusprocesso -52 cerimonial classificacaoprocesso -53 cerimonial topicoprocesso -54 cerimonial assuntoprocesso -55 cerimonial processo -56 cerimonial processocontato -57 cerimonial grupodecontatos -67 core estado -68 cities_light country -69 cities_light region -70 cities_light city -75 cerimonial evento -76 core auditlog +1 admin logentry +2 auth permission +3 auth group +4 contenttypes contenttype +5 sessions session +6 easy_thumbnails source +7 easy_thumbnails thumbnail +8 easy_thumbnails thumbnaildimensions +9 taggit tag +10 taggit taggeditem +11 core user +12 core municipio +13 core nivelinstrucao +14 core situacaomilitar +15 core parlamentar +16 core partido +17 core areatrabalho +18 core operadorareatrabalho +19 core cep +20 core regiaomunicipal +21 core distrito +22 core bairro +23 core tipologradouro +24 core logradouro +25 core trecho +26 core impressoenderecamento +27 core filiacao +28 cerimonial tipotelefone +29 cerimonial tipoendereco +30 cerimonial tipoemail +31 cerimonial parentesco +32 cerimonial estadocivil +33 cerimonial pronometratamento +34 cerimonial tipoautoridade +35 cerimonial tipolocaltrabalho +36 cerimonial nivelinstrucao +37 cerimonial operadoratelefonia +38 cerimonial contato +39 cerimonial perfil +40 cerimonial telefone +41 cerimonial telefoneperfil +42 cerimonial email +43 cerimonial emailperfil +44 cerimonial dependente +45 cerimonial dependenteperfil +46 cerimonial localtrabalho +47 cerimonial localtrabalhoperfil +48 cerimonial endereco +49 cerimonial enderecoperfil +50 cerimonial filiacaopartidaria +51 cerimonial statusprocesso +52 cerimonial classificacaoprocesso +53 cerimonial topicoprocesso +54 cerimonial assuntoprocesso +55 cerimonial processo +56 cerimonial processocontato +57 cerimonial grupodecontatos +67 core estado +68 cities_light country +69 cities_light region +70 cities_light city +75 cerimonial evento +76 core auditlog \. + + -- -- Name: django_content_type_id_seq; Type: SEQUENCE SET; Schema: public; Owner: saap -- From fe8d09ff3ab0662163986c94b7262128cd7ec9d0 Mon Sep 17 00:00:00 2001 From: Jonatha Cardoso Date: Wed, 8 Jun 2022 12:19:50 -0300 Subject: [PATCH 6/7] Update docker.rst MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Correções no processo de carga dos dados iniciais --- docs/docker.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/docker.rst b/docs/docker.rst index 9809bc5..bbcceaf 100644 --- a/docs/docker.rst +++ b/docs/docker.rst @@ -78,7 +78,7 @@ Para que o sistema esteja com os dados iniciais, além das configurações de pe :: - sudo docker cp saap:config/initial_data/django_content.type.sql . + sudo docker cp saap:/var/interlegis/saap/config/initial_data/django_content_type.sql . sudo docker exec -i postgres psql -U saap -d saap < django_content_type.sql :: @@ -87,6 +87,7 @@ Para que o sistema esteja com os dados iniciais, além das configurações de pe ./manage.py loaddata config/initial_data/auth_permission.json ./manage.py loaddata config/initial_data/auth_group.json ./manage.py loaddata config/initial_data/saap_*.json + exit Parar imagens From af404e56f6917272e22dd1d253b028ceeaa94f8f Mon Sep 17 00:00:00 2001 From: Jonatha Cardoso Date: Wed, 8 Jun 2022 15:35:47 -0300 Subject: [PATCH 7/7] Update docker.rst --- docs/docker.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docker.rst b/docs/docker.rst index bbcceaf..cb4aa56 100644 --- a/docs/docker.rst +++ b/docs/docker.rst @@ -83,7 +83,7 @@ Para que o sistema esteja com os dados iniciais, além das configurações de pe :: - sudo docker exec -i saap bash + sudo docker exec -it saap bash ./manage.py loaddata config/initial_data/auth_permission.json ./manage.py loaddata config/initial_data/auth_group.json ./manage.py loaddata config/initial_data/saap_*.json