diff --git a/.gitignore b/.gitignore index b7bc82d..d8af5e7 100644 --- a/.gitignore +++ b/.gitignore @@ -42,3 +42,4 @@ src/brasil/gov/agenda/browser/static/* /.settings/ /local pyvenv.cfg +/local.cfg diff --git a/CHANGES.rst b/CHANGES.rst index dbc8154..90149e7 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,7 +4,10 @@ Changelog 2.0b4 (unreleased) ^^^^^^^^^^^^^^^^^^ -- Nothing changed yet. +- Funcionalidade para exportar os compromissos de uma agenda, em um determinado + período de tempo, no formato CSV. + (closes `#173 `_). + [idgserpro] 2.0b3 (2020-09-29) diff --git a/setup.py b/setup.py index 20616e8..11acf30 100644 --- a/setup.py +++ b/setup.py @@ -3,7 +3,7 @@ from setuptools import find_packages from setuptools import setup -version = '2.0b4.dev0' +version = '2.0b4.dev3' description = 'Agenda de membros do Governo Brasileiro' long_description = ( open('README.rst').read() + '\n' + @@ -41,7 +41,8 @@ zip_safe=False, install_requires=[ 'Acquisition', - 'collective.portlet.calendar', # BBB: https://github.com/plonegovbr/brasil.gov.agenda/issues/137 + # BBB: https://github.com/plonegovbr/brasil.gov.agenda/issues/137 + 'collective.portlet.calendar', 'collective.cover', 'plone.api', 'plone.app.content', 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)) + + +class IExportAgendaForm(interface.Interface): + + initial_date = schema.Date(title=_(u'Initial Date'), + required=True) + + final_date = schema.Date(title=_(u'Final Date'), + required=True) + + review_state = schema.List(title=_(u'Daily Agenda Status'), + required=True, + constraint=requiredConstraint, + value_type=schema.Choice(vocabulary=STATES)) + + +class ExportAgendaForm(form.Form): + """Formulário de exportação de Agenda.""" + fields = field.Fields(IExportAgendaForm) + fields['review_state'].widgetFactory = CheckBoxFieldWidget + ignoreContext = True + + @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) + 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 Compromissos da Agenda.""" + form = ExportAgendaForm + label = _(u'Export Appointments') diff --git a/src/brasil/gov/agenda/locales/brasil.gov.agenda.pot b/src/brasil/gov/agenda/locales/brasil.gov.agenda.pot index 9eabb98..123c941 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-10-01 17:19+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,22 @@ msgstr "" msgid "Compromissos do dia" msgstr "" +#: brasil/gov/agenda/browser/export_agenda.py:221 +msgid "Daily Agenda Status" +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 +127,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:246 +msgid "Export" +msgstr "" + +#: brasil/gov/agenda/browser/export_agenda.py:270 +#: brasil/gov/agenda/profiles/default/actions.xml +msgid "Export Appointments" +msgstr "" + +#: brasil/gov/agenda/browser/export_agenda.py:218 +msgid "Final Date" +msgstr "" + +#: brasil/gov/agenda/browser/export_agenda.py:241 +msgid "Final date greater than 1 year after the initial date" +msgstr "" + +#: brasil/gov/agenda/browser/export_agenda.py:236 +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 +180,10 @@ msgstr "" msgid "Informe o orgao ao qual esta agenda pertence. ex: Presidencia da Republica" msgstr "" +#: brasil/gov/agenda/browser/export_agenda.py:215 +msgid "Initial Date" +msgstr "" + #: brasil/gov/agenda/content/agendadiaria.py:111 msgid "Ja existe uma agenda para esta data" msgstr "" @@ -157,26 +218,38 @@ 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" msgstr "" +#: brasil/gov/agenda/browser/export_agenda.py:46 +msgid "Private" +msgstr "" + +#: brasil/gov/agenda/browser/export_agenda.py:50 +msgid "Published" +msgstr "" + #: brasil/gov/agenda/profiles.zcml:26 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 +257,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 +277,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 +287,10 @@ 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/content/schema/Agenda.xml #: brasil/gov/agenda/content/schema/AgendaDiaria.xml msgid "Tags são utilizadas para organização de conteúdo" @@ -223,7 +308,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 +344,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 "" 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..7850b4c 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-10-01 17:19+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,22 @@ msgstr "Appointments" msgid "Compromissos do dia" msgstr "" +#: brasil/gov/agenda/browser/export_agenda.py:221 +msgid "Daily Agenda Status" +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 +127,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:246 +msgid "Export" +msgstr "" + +#: brasil/gov/agenda/browser/export_agenda.py:270 +#: brasil/gov/agenda/profiles/default/actions.xml +msgid "Export Appointments" +msgstr "" + +#: brasil/gov/agenda/browser/export_agenda.py:218 +msgid "Final Date" +msgstr "" + +#: brasil/gov/agenda/browser/export_agenda.py:241 +msgid "Final date greater than 1 year after the initial date" +msgstr "" + +#: brasil/gov/agenda/browser/export_agenda.py:236 +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 +180,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:215 +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,26 +218,38 @@ 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" msgstr "Agenda" +#: brasil/gov/agenda/browser/export_agenda.py:46 +msgid "Private" +msgstr "" + +#: brasil/gov/agenda/browser/export_agenda.py:50 +msgid "Published" +msgstr "" + #: brasil/gov/agenda/profiles.zcml:26 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 +257,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 +277,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 +287,10 @@ 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/content/schema/Agenda.xml #: brasil/gov/agenda/content/schema/AgendaDiaria.xml msgid "Tags são utilizadas para organização de conteúdo" @@ -223,7 +308,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 +344,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 "" diff --git a/src/brasil/gov/agenda/locales/plone.pot b/src/brasil/gov/agenda/locales/plone.pot index dcd6c11..49fe6ce 100644 --- a/src/brasil/gov/agenda/locales/plone.pot +++ b/src/brasil/gov/agenda/locales/plone.pot @@ -4,7 +4,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" -"POT-Creation-Date: 2019-04-03 13:15+0000\n" +"POT-Creation-Date: 2020-10-01 17:19+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI +ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" 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..2789ce1 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-10-01 17:19+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,22 @@ msgstr "Compromissos" msgid "Compromissos do dia" msgstr "Compromissos do dia" +#: brasil/gov/agenda/browser/export_agenda.py:221 +msgid "Daily Agenda Status" +msgstr "Estado das Agendas Diárias" + +#: 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 +129,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:246 +msgid "Export" +msgstr "Exportar" + +#: brasil/gov/agenda/browser/export_agenda.py:270 +#: brasil/gov/agenda/profiles/default/actions.xml +msgid "Export Appointments" +msgstr "Exportar Compromissos" + +#: brasil/gov/agenda/browser/export_agenda.py:218 +msgid "Final Date" +msgstr "Data Final" + +#: brasil/gov/agenda/browser/export_agenda.py:241 +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:236 +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 +182,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:215 +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,26 +220,38 @@ 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" msgstr "Pauta" +#: brasil/gov/agenda/browser/export_agenda.py:46 +msgid "Private" +msgstr "Privado" + +#: brasil/gov/agenda/browser/export_agenda.py:50 +msgid "Published" +msgstr "Publicado" + #: brasil/gov/agenda/profiles.zcml:26 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 +259,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 +279,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 +289,10 @@ 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/content/schema/Agenda.xml #: brasil/gov/agenda/content/schema/AgendaDiaria.xml msgid "Tags são utilizadas para organização de conteúdo" @@ -225,7 +310,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 +346,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." diff --git a/src/brasil/gov/agenda/locales/pt_BR/LC_MESSAGES/plone.po b/src/brasil/gov/agenda/locales/pt_BR/LC_MESSAGES/plone.po index 7ad53a3..5cb8037 100644 --- a/src/brasil/gov/agenda/locales/pt_BR/LC_MESSAGES/plone.po +++ b/src/brasil/gov/agenda/locales/pt_BR/LC_MESSAGES/plone.po @@ -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-10-01 17:19+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI +ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" 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..c1d3aad --- /dev/null +++ b/src/brasil/gov/agenda/profiles/default/actions.xml @@ -0,0 +1,20 @@ + + + + + Export Appointments + + 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..0615e93 100644 --- a/src/brasil/gov/agenda/profiles/default/metadata.xml +++ b/src/brasil/gov/agenda/profiles/default/metadata.xml @@ -1,6 +1,6 @@ - 4104 + 4106 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..c08a4dd 100644 --- a/src/brasil/gov/agenda/setuphandlers.py +++ b/src/brasil/gov/agenda/setuphandlers.py @@ -15,7 +15,10 @@ def getNonInstallableProducts(): return [ u'brasil.gov.agenda.upgrades.v4101', u'brasil.gov.agenda.upgrades.v4102', + u'brasil.gov.agenda.upgrades.v4103', u'brasil.gov.agenda.upgrades.v4104', + u'brasil.gov.agenda.upgrades.v4105', + u'brasil.gov.agenda.upgrades.v4106', # BBB: https://github.com/plonegovbr/brasil.gov.agenda/issues/137 u'collective.portlet.calendar', ] @@ -44,6 +47,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 +75,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..a6be311 --- /dev/null +++ b/src/brasil/gov/agenda/tests/test_export_agendas.py @@ -0,0 +1,208 @@ +# -*- 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..b9f0c1d 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'4106',)) 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..8b5b434 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 Appointments') + + # Executa upgrade. + self.execute_upgrade_step(step) + + action = object_buttons.listActions()[-1] + self.assertEqual(action.title, u'Export Appointments') + + 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..798fbb6 100644 --- a/src/brasil/gov/agenda/upgrades/configure.zcml +++ b/src/brasil/gov/agenda/upgrades/configure.zcml @@ -4,4 +4,6 @@ + + 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() diff --git a/src/brasil/gov/agenda/upgrades/v4106/__init__.py b/src/brasil/gov/agenda/upgrades/v4106/__init__.py new file mode 100644 index 0000000..40a96af --- /dev/null +++ b/src/brasil/gov/agenda/upgrades/v4106/__init__.py @@ -0,0 +1 @@ +# -*- coding: utf-8 -*- diff --git a/src/brasil/gov/agenda/upgrades/v4106/configure.zcml b/src/brasil/gov/agenda/upgrades/v4106/configure.zcml new file mode 100644 index 0000000..a23e4cb --- /dev/null +++ b/src/brasil/gov/agenda/upgrades/v4106/configure.zcml @@ -0,0 +1,19 @@ + + + + + + + + +