From f71db6d89a9c0bdc6fdd8ee10c22b8cc6b00847c Mon Sep 17 00:00:00 2001 From: idgserpro Date: Mon, 9 Mar 2020 14:28:32 -0300 Subject: [PATCH] Funcionalidade para exportar agenda (#173) Implementa https://github.com/plonegovbr/brasil.gov.agenda/issues/173 --- src/brasil/gov/agenda/browser/configure.zcml | 16 ++ .../gov/agenda/browser/export_agenda.py | 257 ++++++++++++++++++ .../gov/agenda/locales/brasil.gov.agenda.pot | 105 ++++++- .../en/LC_MESSAGES/brasil.gov.agenda.po | 105 ++++++- .../pt_BR/LC_MESSAGES/brasil.gov.agenda.po | 105 ++++++- src/brasil/gov/agenda/permissions.zcml | 5 + .../gov/agenda/profiles/default/actions.xml | 20 ++ .../gov/agenda/profiles/default/metadata.xml | 2 +- .../gov/agenda/profiles/default/rolemap.xml | 4 + src/brasil/gov/agenda/setuphandlers.py | 22 ++ .../gov/agenda/tests/test_export_agendas.py | 220 +++++++++++++++ src/brasil/gov/agenda/tests/test_setup.py | 2 +- src/brasil/gov/agenda/tests/test_upgrades.py | 45 +++ src/brasil/gov/agenda/upgrades/configure.zcml | 1 + .../gov/agenda/upgrades/v4105/__init__.py | 1 + .../gov/agenda/upgrades/v4105/configure.zcml | 29 ++ .../gov/agenda/upgrades/v4105/reindex.py | 34 +++ 17 files changed, 941 insertions(+), 32 deletions(-) create mode 100644 src/brasil/gov/agenda/browser/export_agenda.py create mode 100644 src/brasil/gov/agenda/profiles/default/actions.xml create mode 100644 src/brasil/gov/agenda/tests/test_export_agendas.py create mode 100644 src/brasil/gov/agenda/upgrades/v4105/__init__.py create mode 100644 src/brasil/gov/agenda/upgrades/v4105/configure.zcml create mode 100644 src/brasil/gov/agenda/upgrades/v4105/reindex.py diff --git a/src/brasil/gov/agenda/browser/configure.zcml b/src/brasil/gov/agenda/browser/configure.zcml index 8e0386b..bac0b16 100644 --- a/src/brasil/gov/agenda/browser/configure.zcml +++ b/src/brasil/gov/agenda/browser/configure.zcml @@ -62,6 +62,22 @@ layer="brasil.gov.agenda.interfaces.IBrowserLayer" /> + + + + final_date: + msg = _(u'Final date less than initial date') + raise WidgetActionExecutionError('final_date', Invalid(msg)) + else: + next_year = initial_date + relativedelta(years=1) + if final_date > next_year: + msg = _(u'Final date greater than 1 year after the initial date') + raise WidgetActionExecutionError('final_date', Invalid(msg)) + + @button.buttonAndHandler(_(u'Export'), name='export') + def handleExport(self, action): # @UnusedVariable + data, errors = self.extractData() + initial_date = data.get('initial_date', None) + final_date = data.get('final_date', None) + self.valid_dates(initial_date, final_date) + if errors: + self.status = self.formErrorsMessage + return + + review_state = data['review_state'] + context_url = self.context.absolute_url() + state_url = '' + for state in review_state: + state_url += '&review_state={0}'.format(state.encode('utf-8')) + self.request.RESPONSE.redirect( + '{0}/export_agenda_file?initial_date={1}&final_date={2}{3}'.format( + context_url, initial_date, final_date, state_url), + ) + + +class ExportAgendaFormWrapper(FormWrapper): + """View do formulário de exportação de Agenda.""" + form = ExportAgendaForm + label = _(u'Export Schedule') diff --git a/src/brasil/gov/agenda/locales/brasil.gov.agenda.pot b/src/brasil/gov/agenda/locales/brasil.gov.agenda.pot index 9eabb98..14a1d6a 100644 --- a/src/brasil/gov/agenda/locales/brasil.gov.agenda.pot +++ b/src/brasil/gov/agenda/locales/brasil.gov.agenda.pot @@ -1,7 +1,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" -"POT-Creation-Date: 2019-04-03 13:15+0000\n" +"POT-Creation-Date: 2020-03-12 16:11+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI +ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -22,7 +22,7 @@ msgstr "" msgid ".gov.br: Remoção do suporte a Agenda" msgstr "" -#: brasil/gov/agenda/browser/templates/agenda_macros.pt:89 +#: brasil/gov/agenda/browser/templates/agenda_macros.pt:90 #: brasil/gov/agenda/browser/templates/compromissoview.pt:81 msgid "Adicionar ao meu calendario" msgstr "" @@ -53,14 +53,30 @@ msgstr "" msgid "Agenda do {0}" msgstr "" -#: brasil/gov/agenda/browser/templates/agenda_macros.pt:56 +#: brasil/gov/agenda/browser/templates/agenda_macros.pt:57 msgid "Agora" msgstr "" +#: brasil/gov/agenda/browser/export_agenda.py:33 +msgid "Appointment" +msgstr "" + +#: brasil/gov/agenda/browser/export_agenda.py:38 +msgid "Appointment Agenda" +msgstr "" + +#: brasil/gov/agenda/browser/export_agenda.py:34 +msgid "Appointment Location" +msgstr "" + #: brasil/gov/agenda/content/schema/AgendaDiaria.xml msgid "Atualizacao" msgstr "" +#: brasil/gov/agenda/browser/export_agenda.py:30 +msgid "Authority Name" +msgstr "" + #: brasil/gov/agenda/behaviors/configure.zcml:15 msgid "Automatically generate short URL name for content based on a date field" msgstr "" @@ -87,10 +103,18 @@ msgstr "" msgid "Compromissos do dia" msgstr "" +#: brasil/gov/agenda/browser/export_agenda.py:31 +msgid "Daily Schedule Date" +msgstr "" + #: brasil/gov/agenda/content/schema/AgendaDiaria.xml msgid "Data da Agenda" msgstr "" +#: brasil/gov/agenda/browser/export_agenda.py:29 +msgid "Department Name" +msgstr "" + #: brasil/gov/agenda/content/schema/AgendaDiaria.xml msgid "Descreva aqui se esta agenda foi atualizada. Deixe este campo em branco se nao houver nenhuma atualizacao." msgstr "" @@ -99,14 +123,43 @@ msgstr "" msgid "Detalhe do compromisso" msgstr "" -#: brasil/gov/agenda/browser/templates/agenda_macros.pt:95 +#: brasil/gov/agenda/browser/templates/agenda_macros.pt:96 msgid "Editar" msgstr "" +#: brasil/gov/agenda/browser/export_agenda.py:36 +msgid "End Time" +msgstr "" + +#: brasil/gov/agenda/browser/export_agenda.py:232 +msgid "Export" +msgstr "" + +#: brasil/gov/agenda/browser/export_agenda.py:256 +#: brasil/gov/agenda/profiles/default/actions.xml +msgid "Export Schedule" +msgstr "" + +#: brasil/gov/agenda/browser/export_agenda.py:206 +msgid "Final Date" +msgstr "" + +#: brasil/gov/agenda/browser/export_agenda.py:229 +msgid "Final date greater than 1 year after the initial date" +msgstr "" + +#: brasil/gov/agenda/browser/export_agenda.py:224 +msgid "Final date less than initial date" +msgstr "" + #: brasil/gov/agenda/profiles.zcml:17 msgid "Fornece suporte de agenda de compromissos dentro de um Portal Padrão" msgstr "" +#: brasil/gov/agenda/browser/export_agenda.py:32 +msgid "General information" +msgstr "" + #: brasil/gov/agenda/tiles/agenda.py:27 msgid "Image" msgstr "" @@ -123,6 +176,10 @@ msgstr "" msgid "Informe o orgao ao qual esta agenda pertence. ex: Presidencia da Republica" msgstr "" +#: brasil/gov/agenda/browser/export_agenda.py:203 +msgid "Initial Date" +msgstr "" + #: brasil/gov/agenda/content/agendadiaria.py:111 msgid "Ja existe uma agenda para esta data" msgstr "" @@ -157,16 +214,20 @@ msgstr "" msgid "Orgao" msgstr "" +#: brasil/gov/agenda/browser/export_agenda.py:37 +msgid "Other attendees" +msgstr "" + #: brasil/gov/agenda/content/schema/Compromisso.xml msgid "Outros participantes deste compromisso, um por linha." msgstr "" -#: brasil/gov/agenda/browser/templates/agenda_macros.pt:72 +#: brasil/gov/agenda/browser/templates/agenda_macros.pt:73 #: brasil/gov/agenda/browser/templates/compromissoview.pt:64 msgid "Participante(s)" msgstr "" -#: brasil/gov/agenda/browser/templates/agenda_macros.pt:77 +#: brasil/gov/agenda/browser/templates/agenda_macros.pt:78 #: brasil/gov/agenda/browser/templates/compromissoview.pt:70 #: brasil/gov/agenda/content/schema/Compromisso.xml msgid "Pauta" @@ -176,7 +237,7 @@ msgstr "" msgid "Remove suporte de agenda de compromissos dentro de um Portal Padrão" msgstr "" -#: brasil/gov/agenda/browser/templates/agenda_macros.pt:100 +#: brasil/gov/agenda/browser/templates/agenda_macros.pt:101 msgid "Remover" msgstr "" @@ -184,6 +245,14 @@ msgstr "" msgid "Rodapé da Agenda" msgstr "" +#: brasil/gov/agenda/browser/export_agenda.py:28 +msgid "Schedule Description" +msgstr "" + +#: brasil/gov/agenda/browser/export_agenda.py:27 +msgid "Schedule Title" +msgstr "" + #: brasil/gov/agenda/tiles/agenda.py:50 msgid "Seletor Dia" msgstr "" @@ -196,7 +265,7 @@ msgstr "" msgid "Sem compromissos oficiais." msgstr "" -#: brasil/gov/agenda/browser/templates/agenda_macros.pt:67 +#: brasil/gov/agenda/browser/templates/agenda_macros.pt:68 #: brasil/gov/agenda/browser/templates/compromissoview.pt:59 #: brasil/gov/agenda/content/schema/Compromisso.xml msgid "Solicitante" @@ -206,6 +275,14 @@ msgstr "" msgid "Solicitante da Reuniao e o Orgao ou entidade que representa." msgstr "" +#: brasil/gov/agenda/browser/export_agenda.py:35 +msgid "Start Time" +msgstr "" + +#: brasil/gov/agenda/browser/export_agenda.py:209 +msgid "State" +msgstr "" + #: brasil/gov/agenda/content/schema/Agenda.xml #: brasil/gov/agenda/content/schema/AgendaDiaria.xml msgid "Tags são utilizadas para organização de conteúdo" @@ -223,7 +300,7 @@ msgstr "" msgid "Title" msgstr "" -#: brasil/gov/agenda/browser/templates/agenda_macros.pt:86 +#: brasil/gov/agenda/browser/templates/agenda_macros.pt:87 #: brasil/gov/agenda/browser/templates/compromissoview.pt:79 msgid "VCAL" msgstr "" @@ -259,7 +336,7 @@ msgid "label_event_start" msgstr "" #. Default: "Atualmente não existem compromissos agendados." -#: brasil/gov/agenda/browser/templates/agenda_macros.pt:109 +#: brasil/gov/agenda/browser/templates/agenda_macros.pt:110 msgid "label_no_appointments" msgstr "" @@ -267,3 +344,11 @@ msgstr "" #: brasil/gov/agenda/browser/compromisso.py:64 msgid "long_date_agenda" msgstr "" + +#: brasil/gov/agenda/browser/export_agenda.py:45 +msgid "private" +msgstr "" + +#: brasil/gov/agenda/browser/export_agenda.py:49 +msgid "published" +msgstr "" diff --git a/src/brasil/gov/agenda/locales/en/LC_MESSAGES/brasil.gov.agenda.po b/src/brasil/gov/agenda/locales/en/LC_MESSAGES/brasil.gov.agenda.po index 59d108b..4adb01e 100644 --- a/src/brasil/gov/agenda/locales/en/LC_MESSAGES/brasil.gov.agenda.po +++ b/src/brasil/gov/agenda/locales/en/LC_MESSAGES/brasil.gov.agenda.po @@ -1,7 +1,7 @@ msgid "" msgstr "" "Project-Id-Version: brasil.gov.agenda\n" -"POT-Creation-Date: 2019-04-03 13:15+0000\n" +"POT-Creation-Date: 2020-03-12 16:11+0000\n" "PO-Revision-Date: 2012-09-18 23:00+0000\n" "Last-Translator: PloneGov.Br \n" "Language-Team: PloneGov.Br \n" @@ -22,7 +22,7 @@ msgstr "" msgid ".gov.br: Remoção do suporte a Agenda" msgstr "" -#: brasil/gov/agenda/browser/templates/agenda_macros.pt:89 +#: brasil/gov/agenda/browser/templates/agenda_macros.pt:90 #: brasil/gov/agenda/browser/templates/compromissoview.pt:81 msgid "Adicionar ao meu calendario" msgstr "Add to my calendar" @@ -53,14 +53,30 @@ msgstr "Brazilian government official's schedule" msgid "Agenda do {0}" msgstr "{0}'s Schedule" -#: brasil/gov/agenda/browser/templates/agenda_macros.pt:56 +#: brasil/gov/agenda/browser/templates/agenda_macros.pt:57 msgid "Agora" msgstr "" +#: brasil/gov/agenda/browser/export_agenda.py:33 +msgid "Appointment" +msgstr "" + +#: brasil/gov/agenda/browser/export_agenda.py:38 +msgid "Appointment Agenda" +msgstr "" + +#: brasil/gov/agenda/browser/export_agenda.py:34 +msgid "Appointment Location" +msgstr "" + #: brasil/gov/agenda/content/schema/AgendaDiaria.xml msgid "Atualizacao" msgstr "Update" +#: brasil/gov/agenda/browser/export_agenda.py:30 +msgid "Authority Name" +msgstr "" + #: brasil/gov/agenda/behaviors/configure.zcml:15 msgid "Automatically generate short URL name for content based on a date field" msgstr "" @@ -87,10 +103,18 @@ msgstr "Appointments" msgid "Compromissos do dia" msgstr "" +#: brasil/gov/agenda/browser/export_agenda.py:31 +msgid "Daily Schedule Date" +msgstr "" + #: brasil/gov/agenda/content/schema/AgendaDiaria.xml msgid "Data da Agenda" msgstr "Date of Schedule" +#: brasil/gov/agenda/browser/export_agenda.py:29 +msgid "Department Name" +msgstr "" + #: brasil/gov/agenda/content/schema/AgendaDiaria.xml msgid "Descreva aqui se esta agenda foi atualizada. Deixe este campo em branco se nao houver nenhuma atualizacao." msgstr "Describe here if this schedule has been updated. Leave this field blank if not there is no updating." @@ -99,14 +123,43 @@ msgstr "Describe here if this schedule has been updated. Leave this field blank msgid "Detalhe do compromisso" msgstr "Appointment's details" -#: brasil/gov/agenda/browser/templates/agenda_macros.pt:95 +#: brasil/gov/agenda/browser/templates/agenda_macros.pt:96 msgid "Editar" msgstr "Edit" +#: brasil/gov/agenda/browser/export_agenda.py:36 +msgid "End Time" +msgstr "" + +#: brasil/gov/agenda/browser/export_agenda.py:232 +msgid "Export" +msgstr "" + +#: brasil/gov/agenda/browser/export_agenda.py:256 +#: brasil/gov/agenda/profiles/default/actions.xml +msgid "Export Schedule" +msgstr "" + +#: brasil/gov/agenda/browser/export_agenda.py:206 +msgid "Final Date" +msgstr "" + +#: brasil/gov/agenda/browser/export_agenda.py:229 +msgid "Final date greater than 1 year after the initial date" +msgstr "" + +#: brasil/gov/agenda/browser/export_agenda.py:224 +msgid "Final date less than initial date" +msgstr "" + #: brasil/gov/agenda/profiles.zcml:17 msgid "Fornece suporte de agenda de compromissos dentro de um Portal Padrão" msgstr "" +#: brasil/gov/agenda/browser/export_agenda.py:32 +msgid "General information" +msgstr "" + #: brasil/gov/agenda/tiles/agenda.py:27 msgid "Image" msgstr "" @@ -123,6 +176,10 @@ msgstr "Info" msgid "Informe o orgao ao qual esta agenda pertence. ex: Presidencia da Republica" msgstr "Tell which department this schedule belongs. ex: The Presidency of The Republic" +#: brasil/gov/agenda/browser/export_agenda.py:203 +msgid "Initial Date" +msgstr "" + #: brasil/gov/agenda/content/agendadiaria.py:111 msgid "Ja existe uma agenda para esta data" msgstr "There's already an schedule for this date." @@ -157,16 +214,20 @@ msgstr "Authority's name" msgid "Orgao" msgstr "Department" +#: brasil/gov/agenda/browser/export_agenda.py:37 +msgid "Other attendees" +msgstr "" + #: brasil/gov/agenda/content/schema/Compromisso.xml msgid "Outros participantes deste compromisso, um por linha." msgstr "Other attendees in this appointment, one per line." -#: brasil/gov/agenda/browser/templates/agenda_macros.pt:72 +#: brasil/gov/agenda/browser/templates/agenda_macros.pt:73 #: brasil/gov/agenda/browser/templates/compromissoview.pt:64 msgid "Participante(s)" msgstr "Participants" -#: brasil/gov/agenda/browser/templates/agenda_macros.pt:77 +#: brasil/gov/agenda/browser/templates/agenda_macros.pt:78 #: brasil/gov/agenda/browser/templates/compromissoview.pt:70 #: brasil/gov/agenda/content/schema/Compromisso.xml msgid "Pauta" @@ -176,7 +237,7 @@ msgstr "Agenda" msgid "Remove suporte de agenda de compromissos dentro de um Portal Padrão" msgstr "" -#: brasil/gov/agenda/browser/templates/agenda_macros.pt:100 +#: brasil/gov/agenda/browser/templates/agenda_macros.pt:101 msgid "Remover" msgstr "Remove" @@ -184,6 +245,14 @@ msgstr "Remove" msgid "Rodapé da Agenda" msgstr "Schedule's footer" +#: brasil/gov/agenda/browser/export_agenda.py:28 +msgid "Schedule Description" +msgstr "" + +#: brasil/gov/agenda/browser/export_agenda.py:27 +msgid "Schedule Title" +msgstr "" + #: brasil/gov/agenda/tiles/agenda.py:50 msgid "Seletor Dia" msgstr "" @@ -196,7 +265,7 @@ msgstr "" msgid "Sem compromissos oficiais." msgstr "" -#: brasil/gov/agenda/browser/templates/agenda_macros.pt:67 +#: brasil/gov/agenda/browser/templates/agenda_macros.pt:68 #: brasil/gov/agenda/browser/templates/compromissoview.pt:59 #: brasil/gov/agenda/content/schema/Compromisso.xml msgid "Solicitante" @@ -206,6 +275,14 @@ msgstr "Requester" msgid "Solicitante da Reuniao e o Orgao ou entidade que representa." msgstr "Requester of the Meeting and the Organ or entity it represents." +#: brasil/gov/agenda/browser/export_agenda.py:35 +msgid "Start Time" +msgstr "" + +#: brasil/gov/agenda/browser/export_agenda.py:209 +msgid "State" +msgstr "" + #: brasil/gov/agenda/content/schema/Agenda.xml #: brasil/gov/agenda/content/schema/AgendaDiaria.xml msgid "Tags são utilizadas para organização de conteúdo" @@ -223,7 +300,7 @@ msgstr "" msgid "Title" msgstr "Title" -#: brasil/gov/agenda/browser/templates/agenda_macros.pt:86 +#: brasil/gov/agenda/browser/templates/agenda_macros.pt:87 #: brasil/gov/agenda/browser/templates/compromissoview.pt:79 msgid "VCAL" msgstr "VCAL" @@ -259,7 +336,7 @@ msgid "label_event_start" msgstr "Event Starts" #. Default: "Atualmente não existem compromissos agendados." -#: brasil/gov/agenda/browser/templates/agenda_macros.pt:109 +#: brasil/gov/agenda/browser/templates/agenda_macros.pt:110 msgid "label_no_appointments" msgstr "" @@ -267,3 +344,11 @@ msgstr "" #: brasil/gov/agenda/browser/compromisso.py:64 msgid "long_date_agenda" msgstr "${day} ${month} ${year}" + +#: brasil/gov/agenda/browser/export_agenda.py:45 +msgid "private" +msgstr "" + +#: brasil/gov/agenda/browser/export_agenda.py:49 +msgid "published" +msgstr "" diff --git a/src/brasil/gov/agenda/locales/pt_BR/LC_MESSAGES/brasil.gov.agenda.po b/src/brasil/gov/agenda/locales/pt_BR/LC_MESSAGES/brasil.gov.agenda.po index 1c87f53..f6dc4cb 100644 --- a/src/brasil/gov/agenda/locales/pt_BR/LC_MESSAGES/brasil.gov.agenda.po +++ b/src/brasil/gov/agenda/locales/pt_BR/LC_MESSAGES/brasil.gov.agenda.po @@ -1,7 +1,7 @@ msgid "" msgstr "" "Project-Id-Version: brasil.gov.agenda\n" -"POT-Creation-Date: 2019-04-03 13:15+0000\n" +"POT-Creation-Date: 2020-03-12 16:11+0000\n" "PO-Revision-Date: 2018-09-25 11:03-0300\n" "Last-Translator: PloneGov.Br \n" "Language-Team: PloneGov.Br \n" @@ -24,7 +24,7 @@ msgstr ".gov.br: Agenda de Membros do Governo Brasileiro" msgid ".gov.br: Remoção do suporte a Agenda" msgstr ".gov.br: Remoção do suporte a Agenda" -#: brasil/gov/agenda/browser/templates/agenda_macros.pt:89 +#: brasil/gov/agenda/browser/templates/agenda_macros.pt:90 #: brasil/gov/agenda/browser/templates/compromissoview.pt:81 msgid "Adicionar ao meu calendario" msgstr "Adicionar ao meu calendário" @@ -55,14 +55,30 @@ msgstr "Agenda de um membro do Governo Brasileiro" msgid "Agenda do {0}" msgstr "Agenda do {0}" -#: brasil/gov/agenda/browser/templates/agenda_macros.pt:56 +#: brasil/gov/agenda/browser/templates/agenda_macros.pt:57 msgid "Agora" msgstr "Agora" +#: brasil/gov/agenda/browser/export_agenda.py:33 +msgid "Appointment" +msgstr "Compromisso" + +#: brasil/gov/agenda/browser/export_agenda.py:38 +msgid "Appointment Agenda" +msgstr "Pauta" + +#: brasil/gov/agenda/browser/export_agenda.py:34 +msgid "Appointment Location" +msgstr "Local do Compromisso" + #: brasil/gov/agenda/content/schema/AgendaDiaria.xml msgid "Atualizacao" msgstr "Atualização" +#: brasil/gov/agenda/browser/export_agenda.py:30 +msgid "Authority Name" +msgstr "Nome da Autoridade" + #: brasil/gov/agenda/behaviors/configure.zcml:15 msgid "Automatically generate short URL name for content based on a date field" msgstr "Gera automaticamente um ID a partir de um campo de data." @@ -89,10 +105,18 @@ msgstr "Compromissos" msgid "Compromissos do dia" msgstr "Compromissos do dia" +#: brasil/gov/agenda/browser/export_agenda.py:31 +msgid "Daily Schedule Date" +msgstr "Data da Agenda Diária" + #: brasil/gov/agenda/content/schema/AgendaDiaria.xml msgid "Data da Agenda" msgstr "Data desta Agenda" +#: brasil/gov/agenda/browser/export_agenda.py:29 +msgid "Department Name" +msgstr "Nome do Órgão" + #: brasil/gov/agenda/content/schema/AgendaDiaria.xml msgid "Descreva aqui se esta agenda foi atualizada. Deixe este campo em branco se nao houver nenhuma atualizacao." msgstr "Descreva aqui se esta agenda foi atualizada. Deixe este campo em branco se não houver nenhuma atualização." @@ -101,14 +125,43 @@ msgstr "Descreva aqui se esta agenda foi atualizada. Deixe este campo em branco msgid "Detalhe do compromisso" msgstr "Detalhe do compromisso" -#: brasil/gov/agenda/browser/templates/agenda_macros.pt:95 +#: brasil/gov/agenda/browser/templates/agenda_macros.pt:96 msgid "Editar" msgstr "Editar" +#: brasil/gov/agenda/browser/export_agenda.py:36 +msgid "End Time" +msgstr "Horário de Término" + +#: brasil/gov/agenda/browser/export_agenda.py:232 +msgid "Export" +msgstr "Exportar" + +#: brasil/gov/agenda/browser/export_agenda.py:256 +#: brasil/gov/agenda/profiles/default/actions.xml +msgid "Export Schedule" +msgstr "Exportar Agenda" + +#: brasil/gov/agenda/browser/export_agenda.py:206 +msgid "Final Date" +msgstr "Data Final" + +#: brasil/gov/agenda/browser/export_agenda.py:229 +msgid "Final date greater than 1 year after the initial date" +msgstr "Data final maior que 1 ano após a data inicial" + +#: brasil/gov/agenda/browser/export_agenda.py:224 +msgid "Final date less than initial date" +msgstr "Data final deve ser maior que a data inicial" + #: brasil/gov/agenda/profiles.zcml:17 msgid "Fornece suporte de agenda de compromissos dentro de um Portal Padrão" msgstr "Fornece suporte de agenda de compromissos dentro de um Portal Padrão" +#: brasil/gov/agenda/browser/export_agenda.py:32 +msgid "General information" +msgstr "Informações Gerais" + #: brasil/gov/agenda/tiles/agenda.py:27 msgid "Image" msgstr "Imagem" @@ -125,6 +178,10 @@ msgstr "Info" msgid "Informe o orgao ao qual esta agenda pertence. ex: Presidencia da Republica" msgstr "Informe o órgão ao qual esta agenda pertence. ex: Presidência da República" +#: brasil/gov/agenda/browser/export_agenda.py:203 +msgid "Initial Date" +msgstr "Data Inicial" + #: brasil/gov/agenda/content/agendadiaria.py:111 msgid "Ja existe uma agenda para esta data" msgstr "Já existe uma agenda para esta data." @@ -159,16 +216,20 @@ msgstr "Nome da autoridade" msgid "Orgao" msgstr "Órgão" +#: brasil/gov/agenda/browser/export_agenda.py:37 +msgid "Other attendees" +msgstr "Outros Participantes" + #: brasil/gov/agenda/content/schema/Compromisso.xml msgid "Outros participantes deste compromisso, um por linha." msgstr "Outros participantes deste compromisso, um por linha." -#: brasil/gov/agenda/browser/templates/agenda_macros.pt:72 +#: brasil/gov/agenda/browser/templates/agenda_macros.pt:73 #: brasil/gov/agenda/browser/templates/compromissoview.pt:64 msgid "Participante(s)" msgstr "Participante(s)" -#: brasil/gov/agenda/browser/templates/agenda_macros.pt:77 +#: brasil/gov/agenda/browser/templates/agenda_macros.pt:78 #: brasil/gov/agenda/browser/templates/compromissoview.pt:70 #: brasil/gov/agenda/content/schema/Compromisso.xml msgid "Pauta" @@ -178,7 +239,7 @@ msgstr "Pauta" msgid "Remove suporte de agenda de compromissos dentro de um Portal Padrão" msgstr "Remove suporte de agenda de compromissos dentro de um Portal Padrão" -#: brasil/gov/agenda/browser/templates/agenda_macros.pt:100 +#: brasil/gov/agenda/browser/templates/agenda_macros.pt:101 msgid "Remover" msgstr "Remover" @@ -186,6 +247,14 @@ msgstr "Remover" msgid "Rodapé da Agenda" msgstr "Rodapé da Agenda" +#: brasil/gov/agenda/browser/export_agenda.py:28 +msgid "Schedule Description" +msgstr "Descrição da Agenda" + +#: brasil/gov/agenda/browser/export_agenda.py:27 +msgid "Schedule Title" +msgstr "Título da Agenda" + #: brasil/gov/agenda/tiles/agenda.py:50 msgid "Seletor Dia" msgstr "Seletor dia" @@ -198,7 +267,7 @@ msgstr "Seletor mês" msgid "Sem compromissos oficiais." msgstr "Sem compromissos oficiais." -#: brasil/gov/agenda/browser/templates/agenda_macros.pt:67 +#: brasil/gov/agenda/browser/templates/agenda_macros.pt:68 #: brasil/gov/agenda/browser/templates/compromissoview.pt:59 #: brasil/gov/agenda/content/schema/Compromisso.xml msgid "Solicitante" @@ -208,6 +277,14 @@ msgstr "Solicitante" msgid "Solicitante da Reuniao e o Orgao ou entidade que representa." msgstr "Solicitante da Reunião e o Órgão ou entidade que representa." +#: brasil/gov/agenda/browser/export_agenda.py:35 +msgid "Start Time" +msgstr "Horário de Inicio" + +#: brasil/gov/agenda/browser/export_agenda.py:209 +msgid "State" +msgstr "Estado" + #: brasil/gov/agenda/content/schema/Agenda.xml #: brasil/gov/agenda/content/schema/AgendaDiaria.xml msgid "Tags são utilizadas para organização de conteúdo" @@ -225,7 +302,7 @@ msgstr "Tile que exibe uma agenda" msgid "Title" msgstr "Título" -#: brasil/gov/agenda/browser/templates/agenda_macros.pt:86 +#: brasil/gov/agenda/browser/templates/agenda_macros.pt:87 #: brasil/gov/agenda/browser/templates/compromissoview.pt:79 msgid "VCAL" msgstr "VCAL" @@ -261,7 +338,7 @@ msgid "label_event_start" msgstr "Data e hora de início" #. Default: "Atualmente não existem compromissos agendados." -#: brasil/gov/agenda/browser/templates/agenda_macros.pt:109 +#: brasil/gov/agenda/browser/templates/agenda_macros.pt:110 msgid "label_no_appointments" msgstr "Atualmente não existem compromissos agendados." @@ -269,3 +346,11 @@ msgstr "Atualmente não existem compromissos agendados." #: brasil/gov/agenda/browser/compromisso.py:64 msgid "long_date_agenda" msgstr "${day} de ${month} de ${year}" + +#: brasil/gov/agenda/browser/export_agenda.py:45 +msgid "private" +msgstr "privado" + +#: brasil/gov/agenda/browser/export_agenda.py:49 +msgid "published" +msgstr "publicado" diff --git a/src/brasil/gov/agenda/permissions.zcml b/src/brasil/gov/agenda/permissions.zcml index ff6ac58..9178235 100644 --- a/src/brasil/gov/agenda/permissions.zcml +++ b/src/brasil/gov/agenda/permissions.zcml @@ -17,4 +17,9 @@ title="brasil.gov.agenda: Add Compromisso" /> + + diff --git a/src/brasil/gov/agenda/profiles/default/actions.xml b/src/brasil/gov/agenda/profiles/default/actions.xml new file mode 100644 index 0000000..b18ca70 --- /dev/null +++ b/src/brasil/gov/agenda/profiles/default/actions.xml @@ -0,0 +1,20 @@ + + + + + Export Schedule + + string:$object_url/export_agenda + + + python:object.portal_type == 'Agenda' + + + + True + + + \ No newline at end of file diff --git a/src/brasil/gov/agenda/profiles/default/metadata.xml b/src/brasil/gov/agenda/profiles/default/metadata.xml index 9e26bda..e747933 100644 --- a/src/brasil/gov/agenda/profiles/default/metadata.xml +++ b/src/brasil/gov/agenda/profiles/default/metadata.xml @@ -1,6 +1,6 @@ - 4104 + 4105 profile-collective.cover:default profile-plone.app.dexterity:default diff --git a/src/brasil/gov/agenda/profiles/default/rolemap.xml b/src/brasil/gov/agenda/profiles/default/rolemap.xml index 9f3e568..e183fc9 100644 --- a/src/brasil/gov/agenda/profiles/default/rolemap.xml +++ b/src/brasil/gov/agenda/profiles/default/rolemap.xml @@ -19,5 +19,9 @@ + + + + \ No newline at end of file diff --git a/src/brasil/gov/agenda/setuphandlers.py b/src/brasil/gov/agenda/setuphandlers.py index da4425b..98311c7 100644 --- a/src/brasil/gov/agenda/setuphandlers.py +++ b/src/brasil/gov/agenda/setuphandlers.py @@ -16,6 +16,7 @@ def getNonInstallableProducts(): u'brasil.gov.agenda.upgrades.v4101', u'brasil.gov.agenda.upgrades.v4102', u'brasil.gov.agenda.upgrades.v4104', + u'brasil.gov.agenda.upgrades.v4105', # BBB: https://github.com/plonegovbr/brasil.gov.agenda/issues/137 u'collective.portlet.calendar', ] @@ -44,6 +45,26 @@ def list_agendadiaria_calendar(p): calendar.calendar_types = tuple(types) +def setup_catalog(portal): + """ Cria indice e metadados no catalog. + Foi feito aqui em vez de em profiles/default/catalog.xml para que + não precise reindexar esses índices após cada reinstalação. + https://docs.plone.org/develop/plone/searching_and_indexing/indexing.html#adding-index-using-add-on-product-installer + """ + catalog = api.portal.get_tool('portal_catalog') + + if 'date' not in catalog.indexes(): + catalog.addIndex('date', 'DateIndex') + + metadatas = ['date', 'autoridade', 'attendees'] + + idsMetadatas = catalog.schema() + + for metadata in metadatas: + if metadata not in idsMetadatas: + catalog.addColumn(metadata) + + def setup_site(context): """ Ajustamos o site para receber o produto de agenda """ @@ -52,3 +73,4 @@ def setup_site(context): return site = context.getSite() list_agendadiaria_calendar(site) + setup_catalog(site) diff --git a/src/brasil/gov/agenda/tests/test_export_agendas.py b/src/brasil/gov/agenda/tests/test_export_agendas.py new file mode 100644 index 0000000..3e0ed14 --- /dev/null +++ b/src/brasil/gov/agenda/tests/test_export_agendas.py @@ -0,0 +1,220 @@ +# -*- coding: utf-8 -*- +"""Testes da exportação de Agendas.""" + +from brasil.gov.agenda.testing import INTEGRATION_TESTING +from plone import api +from plone.app.testing import setRoles +from plone.app.testing import TEST_USER_ID +from plone.app.textfield.value import RichTextValue + +import datetime +import unittest + + +class TestExportAgendaFile(unittest.TestCase): + + layer = INTEGRATION_TESTING + + def setUp(self): + self.portal = self.layer['portal'] + self.request = self.layer['request'] + setRoles(self.portal, TEST_USER_ID, ['Site Administrator']) + ltool = api.portal.get_tool('portal_languages') + ltool.setLanguageBindings() + self.agenda = api.content.create( + self.portal, + 'Agenda', + 'agenda', + u'Agenda de Autoridade', + description=u'Agenda de José', + orgao=u'Órgão de José', + autoridade=u'José', + location=u'Local', + update=RichTextValue(u'Atualização', + 'text/html', + 'text/x-html-safe', + encoding='utf-8'), + ) + agenda_diariaPublica = api.content.create( + self.agenda, 'AgendaDiaria', '2019-12-01') + api.content.transition(obj=agenda_diariaPublica, transition='publish') + agenda_diariaPrivada = api.content.create( + self.agenda, 'AgendaDiaria', '2019-12-25') + api.content.create( + agenda_diariaPublica, + 'Compromisso', + 'compromisso01', + u'Compromisso 01', + start_date=datetime.datetime(2019, 12, 1, 12, 0), + end_date=datetime.datetime(2019, 12, 1, 13, 0), + description=u'Pauta 01', + attendees=u'Maria', + ) + api.content.create( + agenda_diariaPrivada, + 'Compromisso', + 'compromisso25', + u'Compromisso 25', + start_date=datetime.datetime(2019, 12, 25, 8, 0), + end_date=datetime.datetime(2019, 12, 25, 9, 0), + description=u'Pauta 25', + attendees=u'Marta', + ) + + def test_file_without_date_and_state(self): + """Testa o arquivo quando não são passadas datas e estado.""" + view = api.content.get_view( + 'export_agenda_file', self.agenda, self.request) + self.assertFalse(view()) + + def test_get_compromissos_all(self): + """Testa get_compromissos retornando todos os Compromissos.""" + self.request.set('initial_date', '2019-01-01') + self.request.set('final_date', '2019-12-25') + self.request.set('review_state', ['private', 'published']) + view = api.content.get_view( + 'export_agenda_file', self.agenda, self.request) + compormissos = view.get_compromissos() + self.assertEqual(len(compormissos), 2) + + def test_get_compromissos_less(self): + """Testa get_compromissos retornando o menor Compromisso.""" + self.request.set('initial_date', '2019-01-01') + self.request.set('final_date', '2019-12-01') + self.request.set('review_state', ['published']) + view = api.content.get_view( + 'export_agenda_file', self.agenda, self.request) + compormissos = view.get_compromissos() + self.assertEqual(len(compormissos), 1) + self.assertEqual(compormissos[0]['compromisso'], 'Compromisso 01') + + def test_get_compromissos_more(self): + """Testa get_compromissos retornando o maior Compromisso.""" + self.request.set('initial_date', '2019-12-25') + self.request.set('final_date', '2019-12-25') + self.request.set('review_state', ['private']) + view = api.content.get_view( + 'export_agenda_file', self.agenda, self.request) + compormissos = view.get_compromissos() + self.assertEqual(len(compormissos), 1) + self.assertEqual(compormissos[0]['compromisso'], 'Compromisso 25') + + def test_write_csv(self): + """Testa a geração do arquivo csv.""" + self.request.set('initial_date', '2019-01-01') + self.request.set('final_date', '2019-12-25') + self.request.set('review_state', ['private', 'published']) + view = api.content.get_view( + 'export_agenda_file', self.agenda, self.request) + csv = view.write_csv() + linha0 = '"Título da Agenda","Descrição da Agenda","Nome do Órgão","Nome da Autoridade",' + '"Data da Agenda Diária","Informações Gerais","Compromisso","Local do Compromisso",' + '"Horário de Inicio","Horário de Término","Outros Participantes,Pauta"' + linha1 = '"Agenda de Autoridade","Agenda de José","Órgão de José","José"' + '"01/12/2019","Atualização","Compromisso 01","Local"' + '"12:00","13:00","Maria","Pauta 01"' + linha2 = '"Agenda de Autoridade","Agenda de José","Órgão de José","José"' + '"25/12/2019","Atualização","Compromisso 25","Local"' + '"08:00","09:00","Marta","Pauta 25"' + self.assertIn(linha0, csv) + self.assertIn(linha1, csv) + self.assertIn(linha2, csv) + + def test_export_agenda_file(self): + """Testa a view export_agenda_file.""" + self.request.set('initial_date', '2019-01-01') + self.request.set('final_date', '2019-12-25') + self.request.set('review_state', ['private', 'published']) + view = api.content.get_view( + 'export_agenda_file', self.agenda, self.request) + render_view = view() + linha0 = '"Título da Agenda","Descrição da Agenda","Nome do Órgão","Nome da Autoridade",' + '"Data da Agenda Diária","Informações Gerais","Compromisso","Local do Compromisso",' + '"Horário de Inicio","Horário de Término","Outros Participantes,Pauta"' + linha1 = '"Agenda de Autoridade","Agenda de José","Órgão de José","José"' + '"01/12/2019","Atualização","Compromisso 01","Local"' + '"12:00","13:00","Maria","Pauta 01"' + linha2 = '"Agenda de Autoridade","Agenda de José","Órgão de José","José"' + '"25/12/2019","Atualização","Compromisso 25","Local"' + '"08:00","09:00","Marta","Pauta 25"' + self.assertIn(linha0, render_view) + self.assertIn(linha1, render_view) + self.assertIn(linha2, render_view) + headers = self.request.response.headers + self.assertEqual(headers['content-type'], 'text/csv') + self.assertEqual( + headers['content-disposition'], 'attachment; filename="agenda.csv"') + + +class TestExportAgendaForm(unittest.TestCase): + + layer = INTEGRATION_TESTING + + def setUp(self): + self.portal = self.layer['portal'] + self.request = self.layer['request'] + setRoles(self.portal, TEST_USER_ID, ['Site Administrator']) + self.agenda = api.content.create( + self.portal, + 'Agenda', + 'agenda', + u'Agenda de Autoridade', + autoridade=u'José', + ) + self.view = api.content.get_view( + 'export_agenda', self.agenda, self.request) + + def test_fields_requires(self): + """Testa os campos requeridos do form.""" + self.request.set('form.buttons.export', u'Export') + html = self.view() + self.assertIn('There were some errors', html) + num_requires = html.count('Required input is missing.') + self.assertEqual(num_requires, 3) + + def test_final_greater_initial(self): + """Testa a validação da data final maior que a inicial.""" + self.request.set('form.widgets.initial_date-day', u'29') + self.request.set('form.widgets.initial_date-month', u'12') + self.request.set('form.widgets.initial_date-year', u'2020') + self.request.set('form.widgets.final_date-day', u'01') + self.request.set('form.widgets.final_date-month', u'12') + self.request.set('form.widgets.final_date-year', u'2020') + self.request.set('form.widgets.review_state', u'private') + self.request.set('form.buttons.export', u'Export') + html = self.view() + self.assertIn('There were some errors', html) + self.assertIn('Final date less than initial date', html) + + def test_final_greater_year(self): + """Testa a validação da data final maior que 1 ano da inicial.""" + self.request.set('form.widgets.initial_date-day', u'01') + self.request.set('form.widgets.initial_date-month', u'12') + self.request.set('form.widgets.initial_date-year', u'2019') + self.request.set('form.widgets.final_date-day', u'02') + self.request.set('form.widgets.final_date-month', u'12') + self.request.set('form.widgets.final_date-year', u'2020') + self.request.set('form.widgets.review_state', u'private') + self.request.set('form.buttons.export', u'Export') + html = self.view() + self.assertIn('There were some errors', html) + self.assertIn('Final date greater than 1 year after the initial date', html) + + def test_form_export_redirect(self): + """Testa o form redireciona para a view que gera o arquivo.""" + self.request.set('form.widgets.initial_date-day', u'29') + self.request.set('form.widgets.initial_date-month', u'11') + self.request.set('form.widgets.initial_date-year', u'2019') + self.request.set('form.widgets.final_date-day', u'25') + self.request.set('form.widgets.final_date-month', u'12') + self.request.set('form.widgets.final_date-year', u'2019') + self.request.set('form.widgets.review_state', u'private') + self.request.set('form.buttons.export', u'Export') + self.view() + location = self.request.response.getHeader('location') + self.assertEqual( + 'http://nohost/plone/agenda/export_agenda_file?' + 'initial_date=2019-11-29&final_date=2019-12-25' + '&review_state=private', + location, + ) diff --git a/src/brasil/gov/agenda/tests/test_setup.py b/src/brasil/gov/agenda/tests/test_setup.py index 53dc40f..517b891 100644 --- a/src/brasil/gov/agenda/tests/test_setup.py +++ b/src/brasil/gov/agenda/tests/test_setup.py @@ -40,7 +40,7 @@ def test_installed(self): def test_version(self): self.assertEqual( - self.st.getLastVersionForProfile(self.profile), (u'4104',)) + self.st.getLastVersionForProfile(self.profile), (u'4105',)) def test_agenda_not_searched(self): pp = getattr(self.portal, 'portal_properties') diff --git a/src/brasil/gov/agenda/tests/test_upgrades.py b/src/brasil/gov/agenda/tests/test_upgrades.py index 9d8521a..b1b592d 100644 --- a/src/brasil/gov/agenda/tests/test_upgrades.py +++ b/src/brasil/gov/agenda/tests/test_upgrades.py @@ -163,3 +163,48 @@ def test_deprecate_resource_registries(self): self.assertNotIn(js, js_tool.getResourceIds()) for css in STYLES: self.assertNotIn(css, css_tool.getResourceIds()) + + +class to4105TestCase(UpgradeTestCaseBase): + + def setUp(self): + UpgradeTestCaseBase.setUp(self, u'4104', u'4105') + + def test_registrations(self): + version = self.setup.getLastVersionForProfile(self.profile_id)[0] + self.assertGreaterEqual(int(version), int(self.to_version)) + self.assertEqual(self.total_steps, 3) + + def test_add_export_agenda_action(self): + # check if the upgrade step is registered + title = u'Adiciona action Exportar Agenda' + step = self.get_upgrade_step(title) + self.assertIsNotNone(step) + + portal_actions = api.content.portal.get_tool('portal_actions') + object_buttons = portal_actions.object_buttons + object_buttons.manage_delObjects(['export_agenda']) + action = object_buttons.listActions()[-1] + self.assertNotEqual(action.title, u'Export Schedule') + + # Executa upgrade. + self.execute_upgrade_step(step) + + action = object_buttons.listActions()[-1] + self.assertEqual(action.title, u'Export Schedule') + + def test_permission(self): + permission = 'brasil.gov.agenda: Exportar Agenda' + roles = self.portal.rolesOfPermission(permission) + roles = [r['name'] for r in roles if r['selected']] + expected = ['Manager', 'Site Administrator'] + self.assertListEqual(roles, expected) + + def test_setup_catalog(self): + catalog = api.portal.get_tool('portal_catalog') + self.assertIn('date', catalog.indexes()) + + metadatas = ['date', 'autoridade', 'attendees'] + idsMetadatas = catalog.schema() + for metadata in metadatas: + self.assertIn(metadata, idsMetadatas) diff --git a/src/brasil/gov/agenda/upgrades/configure.zcml b/src/brasil/gov/agenda/upgrades/configure.zcml index f673c33..fcac8dd 100644 --- a/src/brasil/gov/agenda/upgrades/configure.zcml +++ b/src/brasil/gov/agenda/upgrades/configure.zcml @@ -4,4 +4,5 @@ + diff --git a/src/brasil/gov/agenda/upgrades/v4105/__init__.py b/src/brasil/gov/agenda/upgrades/v4105/__init__.py new file mode 100644 index 0000000..40a96af --- /dev/null +++ b/src/brasil/gov/agenda/upgrades/v4105/__init__.py @@ -0,0 +1 @@ +# -*- coding: utf-8 -*- diff --git a/src/brasil/gov/agenda/upgrades/v4105/configure.zcml b/src/brasil/gov/agenda/upgrades/v4105/configure.zcml new file mode 100644 index 0000000..608e2d5 --- /dev/null +++ b/src/brasil/gov/agenda/upgrades/v4105/configure.zcml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + diff --git a/src/brasil/gov/agenda/upgrades/v4105/reindex.py b/src/brasil/gov/agenda/upgrades/v4105/reindex.py new file mode 100644 index 0000000..ee50184 --- /dev/null +++ b/src/brasil/gov/agenda/upgrades/v4105/reindex.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +from brasil.gov.agenda.setuphandlers import setup_catalog +from plone import api + +import transaction + + +def reindex_catalog(context): + """ Cria e reindexa o indice date e os metadados autoridade, update e attendees + Segue orientação: + https://community.plone.org/t/best-practices-on-reindexing-the-catalog/4157/14 + """ + setup_catalog(context) + catalog = api.portal.get_tool('portal_catalog') + + # Agendas diárias + n = 0 + agendas = catalog(portal_type='AgendaDiaria') + for agenda in agendas: + obj_agenda = agenda.getObject() + catalog.catalog_object(obj_agenda, idxs=['date'], update_metadata=True) + n += 1 + if n % 1000 == 0: + transaction.commit() + + # Compromissos + n = 0 + compromissos = catalog(portal_type='Compromisso') + for compromisso in compromissos: + obj_compromisso = compromisso.getObject() + catalog.catalog_object(obj_compromisso, idxs=[], update_metadata=True) + n += 1 + if n % 1000 == 0: + transaction.commit()