Ejemplo n.º 1
0
    def generate_zip(self):
        response = self.request.response

        with ZipGenerator() as generator:
            # Protocol
            generator.add_file(*self.get_protocol())

            # Agenda items
            self.add_agenda_items_attachments(generator)
            if is_word_meeting_implementation_enabled():
                self.add_agenda_item_proposal_documents(generator)

            # Agenda items list
            try:
                generator.add_file(*self.get_agendaitem_list())
            except AgendaItemListMissingTemplate:
                pass

            if is_word_meeting_implementation_enabled():
                generator.add_file(*self.get_meeting_json())

            # Return zip
            zip_file = generator.generate()
            filename = '{}.zip'.format(normalize_path(self.model.title))
            response.setHeader(
                "Content-Disposition",
                'inline; filename="{0}"'.format(
                    safe_unicode(filename).encode('utf-8')))
            response.setHeader("Content-type", "application/zip")
            response.setHeader(
                "Content-Length",
                os.stat(zip_file.name).st_size)

            return filestream_iterator(zip_file.name, 'rb')
Ejemplo n.º 2
0
    def execute(self):
        model = self.proposal.load_model()
        jsondata = {'committee_oguid': model.committee.oguid.id,
                    'proposal_oguid': model.oguid.id}

        # XXX use Transporter or API?
        collector = getMultiAdapter((self.proposal,), IDataCollector,
                                    name='field-data')
        jsondata['field-data'] = collector.extract()

        if is_word_meeting_implementation_enabled():
            blob = self.proposal.get_proposal_document().file
            jsondata['file'] = {
                'filename': blob.filename,
                'contentType': blob.contentType,
                'data': base64.encodestring(blob.data)}

        record = IHistory(self.proposal).append_record(u'submitted')
        history_data = advancedjson.dumps({'uuid': record.uuid})

        request_data = {
            REQUEST_KEY: json.dumps(decode_for_json(jsondata)),
            'history_data': history_data}
        response = dispatch_json_request(
            self.admin_unit_id, '@@create_submitted_proposal', data=request_data)

        self.submitted_proposal_path = response['path']
Ejemplo n.º 3
0
    def _checkin_proposal_document_before_deciding(self):
        if not is_word_meeting_implementation_enabled():
            # old implementation: there is no proposal document
            return

        if not self.agenda_item.has_proposal:
            # no proposal => no document to checkin
            return

        submitted_proposal = self.agenda_item.proposal.resolve_submitted_proposal(
        )
        document = submitted_proposal.get_proposal_document()
        checkout_manager = getMultiAdapter((document, self.request),
                                           ICheckinCheckoutManager)
        if checkout_manager.get_checked_out_by() is None:
            # document is not checked out
            return

        if not checkout_manager.is_checkin_allowed():
            return JSONResponse(self.request).error(
                _('agenda_item_cannot_decide_document_checked_out',
                  default=u'Cannot decide agenda item: someone else has'
                  u' checked out the document.')).remain().dump()

        checkout_manager.checkin()
Ejemplo n.º 4
0
def excerpt_template_constraint(value):
    if is_word_meeting_implementation_enabled():
        # The excerpt template is not used when word-meeting feature is enabled
        return True
    if not value:
        raise Invalid()
    return True
Ejemplo n.º 5
0
    def get_overview_attributes(self):
        data = super(SubmittedProposal, self).get_overview_attributes()
        model = self.load_model()

        # Insert dossier link if dossier exists after committee
        data.insert(
            2, {
                'label': _('label_dossier', default=u"Dossier"),
                'value': self.get_dossier_link(),
                'is_html': True,
            })

        if not is_word_meeting_implementation_enabled():
            # Insert considerations after proposed_action
            data.insert(
                7, {
                    'label': _('label_considerations',
                               default=u"Considerations"),
                    'value': self.considerations,
                })

            # Insert discussion after considerations
            agenda = model.agenda_item
            data.insert(
                8, {
                    'label': _('label_discussion', default=u"Discussion"),
                    'value': agenda and agenda.discussion or ''
                })

        return data
Ejemplo n.º 6
0
    def update_protocol_document(self):
        """Update or create meeting's protocol."""
        from opengever.meeting.command import CreateGeneratedDocumentCommand
        from opengever.meeting.command import MergeDocxProtocolCommand
        from opengever.meeting.command import ProtocolOperations
        from opengever.meeting.command import UpdateGeneratedDocumentCommand

        if self.has_protocol_document(
        ) and not self.protocol_document.is_locked():
            # The protocol should never be changed when it is no longer locked:
            # the user probably has made changes manually.
            return

        operations = ProtocolOperations()

        if is_word_meeting_implementation_enabled():
            command = MergeDocxProtocolCommand(
                self.get_dossier(),
                self,
                operations,
                lock_document_after_creation=True)
        else:
            if self.has_protocol_document():
                command = UpdateGeneratedDocumentCommand(
                    self.protocol_document, self, operations)
            else:
                command = CreateGeneratedDocumentCommand(
                    self.get_dossier(),
                    self,
                    operations,
                    lock_document_after_creation=True)

        command.execute()
Ejemplo n.º 7
0
    def create_proposal_document(self, source_blob=None, **kwargs):
        """Creates a proposal document within this proposal or submitted
        proposal.
        Only one proposal document can be created.
        """
        if not is_word_meeting_implementation_enabled():
            raise WordMeetingImplementationDisabledError()

        if self.get_proposal_document():
            raise ValueError('There is already a proposal document.')

        if source_blob:
            kwargs.setdefault('filename', source_blob.filename)
            kwargs.setdefault('data', source_blob.open().read())
            kwargs.setdefault('content_type', source_blob.contentType)

        kwargs['context'] = self
        kwargs.setdefault('preserved_as_paper', False)

        title = _(u'proposal_document_title',
                  default=u'Proposal document ${title}',
                  mapping={'title': safe_unicode(self.Title())})
        title = translate(title, context=self.REQUEST).strip()
        kwargs.setdefault('title', title)

        with elevated_privileges():
            obj = CreateDocumentCommand(**kwargs).execute()

        self._proposal_document_uuid = IUUID(obj)
        return obj
    def render(self):
        jsondata = self.request.get(REQUEST_KEY)
        data = encode_after_json(json.loads(jsondata))
        committee = Oguid.parse(data['committee_oguid']).resolve_object()
        proposal_oguid = Oguid.parse(data['proposal_oguid'])
        proposal = meeting_service().fetch_proposal_by_oguid(proposal_oguid)

        with elevated_privileges():
            submitted_proposal = SubmittedProposal.create(proposal, committee)

            # XXX use Transporter API?
            collector = getMultiAdapter((submitted_proposal, ),
                                        IDataCollector,
                                        name='field-data')
            data['field-data']['ISubmittedProposal'] = data['field-data'].pop(
                'IProposal')
            collector.insert(data['field-data'])

            if is_word_meeting_implementation_enabled():
                submitted_proposal.create_proposal_document(
                    filename=data['file']['filename'],
                    content_type=data['file']['contentType'].encode('utf-8'),
                    data=base64.decodestring(data['file']['data']))

            history_data = advancedjson.loads(self.request.get('history_data'))
            IHistory(submitted_proposal).append_record(
                u'submitted', uuid=history_data['uuid'])

            self.request.response.setHeader("Content-type", "application/json")
            return json.dumps(
                {'path': '/'.join(submitted_proposal.getPhysicalPath())})
Ejemplo n.º 9
0
    def schedule_text(self):
        """Schedule the given Text (request parameter `title`) for the current
        meeting.
        """
        self.check_editable()
        title = safe_unicode(self.request.get('title'))
        if not title:
            return JSONResponse(self.request).error(
                _('empty_proposal',
                  default=u"Proposal must not be empty.")).proceed().dump()

        if is_word_meeting_implementation_enabled():
            try:
                self.meeting.schedule_ad_hoc(title)
            except MissingAdHocTemplate:
                return JSONResponse(self.request).error(
                    _('missing_ad_hoc_template',
                      default=u"No ad-hoc agenda-item template has been "
                      u"configured.")).remain().dump()
            except MissingMeetingDossierPermissions:
                return JSONResponse(self.request).error(
                    _('error_no_permission_to_add_document',
                      default=u'Insufficient privileges to add a'
                      u' document to the meeting dossier.')).remain().dump()

        else:
            self.meeting.schedule_text(title)

        return JSONResponse(self.request).info(
            _('text_added',
              default=u"Text successfully added.")).proceed().dump()
Ejemplo n.º 10
0
    def get_protocol(self):
        if self.model.has_protocol_document():
            protocol = self.model.protocol_document.resolve_document()
            protocol_modified = protocol.modified().asdatetime().astimezone(
                pytz.utc)

            if self.model.modified < protocol_modified:
                # Return current protocol
                return (u'{}.docx'.format(safe_unicode(protocol.Title())),
                        protocol.file.open())

        # Create new protocol
        operations = ProtocolOperations()
        if is_word_meeting_implementation_enabled():
            command_class = MergeDocxProtocolCommand
        else:
            command_class = CreateGeneratedDocumentCommand
        command = command_class(
            self.context,
            self.model,
            operations,
            lock_document_after_creation=False)

        filename = u'{}.docx'.format(operations.get_title(self.model))
        return (filename, StringIO(command.generate_file_data()))
Ejemplo n.º 11
0
    def updateWidgets(self):
        super(AddForm, self).updateWidgets()

        if not is_word_meeting_implementation_enabled():
            self.widgets['ad_hoc_template'].mode = HIDDEN_MODE
            self.widgets['paragraph_template'].mode = HIDDEN_MODE
        else:
            self.widgets['excerpt_template'].mode = HIDDEN_MODE
Ejemplo n.º 12
0
    def proposal_templates_tab(self):
        if is_word_meeting_implementation_enabled():
            return {
                'id': 'proposaltemplates-proxy',
                'title': _(u'label_proposal_templates', default=u'Proposal Templates'),
                }

        return None
Ejemplo n.º 13
0
    def url_generate_protocol(self):
        if is_word_meeting_implementation_enabled():
            return self.url_merge_docx_protocol()

        if not self.model.has_protocol_document():
            return GenerateProtocol.url_for(self.model)
        else:
            return UpdateProtocol.url_for(self.model)
Ejemplo n.º 14
0
 def __call__(self):
     self.install_upgrade_profile()
     if is_word_meeting_implementation_enabled():
         query = {
             'object_provides':
             'opengever.meeting.proposal.ISubmittedProposal'
         }
         for obj in self.objects(query, self.__class__.__doc__):
             addRelations(obj, None)
Ejemplo n.º 15
0
    def updateFields(self):
        super(FieldConfigurationMixin, self).updateFields()
        textfields = ('legal_basis', 'initial_position', 'proposed_action',
                      'decision_draft', 'publish_in', 'disclose_to',
                      'copy_for_attention')

        map(self.use_trix, textfields)
        if is_word_meeting_implementation_enabled():
            map(self.omit_field, textfields)
Ejemplo n.º 16
0
    def visible_in_actions_menu(self):
        """Returns ``True`` when the zip export action should be displayed
        in the actions menu.

        The action should only appear when we are on a meeting view and the
        word-meeting feature is enabled.
        """
        return IMeetingWrapper.providedBy(self.context) and \
            is_word_meeting_implementation_enabled()
Ejemplo n.º 17
0
    def get_decision_number(self):
        if not is_word_meeting_implementation_enabled():
            return self.decision_number

        if not self.decision_number:
            return self.decision_number

        period = Period.query.get_current_for_update(self.meeting.committee)
        year = period.date_from.year
        return '{} / {}'.format(year, self.decision_number)
Ejemplo n.º 18
0
    def createAndAdd(self, data):
        if not is_word_meeting_implementation_enabled():
            return super(AddForm, self).createAndAdd(data)

        proposal_template = data.pop('proposal_template')
        self.instance_schema = IProposal
        noaq_proposal = super(AddForm, self).createAndAdd(data)
        proposal = self.context.get(noaq_proposal.getId())
        proposal.create_proposal_document(proposal_template.file)
        return proposal
Ejemplo n.º 19
0
    def __call__(self):
        if is_word_meeting_implementation_enabled():
            # Enable border to show the zip export action also for
            # committee members. Because the plone_view's `showEditableBorder`
            # checks for `ModifyPortalContent`, we have to enable the border
            # manually.
            self.request.set('enable_border', True)

            return self.word_template()
        else:
            return self.noword_template()
Ejemplo n.º 20
0
 def updateFields(self):
     super(CommitteContainerFieldConfigurationMixin, self).updateFields()
     if is_word_meeting_implementation_enabled():
         self.fields = self.fields.omit('excerpt_template',
                                        'protocol_template')
     else:
         self.fields = self.fields.omit(
             'ad_hoc_template', 'paragraph_template',
             'protocol_header_template', 'protocol_suffix_template',
             'agenda_item_header_template', 'agenda_item_suffix_template',
             'excerpt_header_template', 'excerpt_suffix_template')
Ejemplo n.º 21
0
        def filter_type(fti):
            factory_type = fti.id
            if factory_type in [u'opengever.meeting.sablontemplate']:
                return is_meeting_feature_enabled()

            if factory_type in [u'opengever.meeting.proposaltemplate']:
                return is_word_meeting_implementation_enabled()

            if factory_type in [u'opengever.dossier.dossiertemplate']:
                return is_dossier_template_feature_enabled()

            return True
Ejemplo n.º 22
0
    def get_documents(self):
        catalog = api.portal.get_tool('portal_catalog')
        documents = catalog(
            portal_type=['opengever.document.document', 'ftw.mail.mail'],
            path=dict(query='/'.join(self.getPhysicalPath())),
            sort_on='sortable_title')

        ignored_documents = [self.get_excerpt()]
        if is_word_meeting_implementation_enabled():
            ignored_documents.append(self.get_proposal_document())

        all_docs = [document.getObject() for document in documents]
        return [doc for doc in all_docs if doc not in ignored_documents]
Ejemplo n.º 23
0
    def get_items(self):
        if not is_word_meeting_implementation_enabled():
            return []

        items = []

        for item in self.byline_items():
            item['content'] = safe_unicode(item['content'])
            item.setdefault('class', '')
            item.setdefault('replace', False)
            items.append(item)

        return items
Ejemplo n.º 24
0
    def _get_agenda_items(self):
        meeting = self.meeting
        agenda_items = []
        for item in meeting.agenda_items:
            data = item.serialize()
            data['documents'] = self._serialize_submitted_documents(item)
            data['excerpt'] = self._serialize_submitted_excerpt(item)
            data['has_documents'] = self.has_documents(item)
            data['delete_link'] = meeting.get_url(
                view='agenda_items/{}/delete'.format(item.agenda_item_id))
            data['edit_link'] = meeting.get_url(
                view='agenda_items/{}/edit'.format(item.agenda_item_id))
            data['decision_number'] = item.get_decision_number()
            data['is_decided'] = item.is_decided()
            if item.is_decide_possible():
                data['decide_link'] = meeting.get_url(
                    view='agenda_items/{}/decide'.format(item.agenda_item_id))
            if item.is_reopen_possible():
                data['reopen_link'] = meeting.get_url(
                    view='agenda_items/{}/reopen'.format(item.agenda_item_id))
            if item.is_revise_possible():
                data['revise_link'] = meeting.get_url(
                    view='agenda_items/{}/revise'.format(item.agenda_item_id))
            if item.is_paragraph:
                data['paragraph'] = True
            if is_word_meeting_implementation_enabled():
                document = item.resolve_document()
                if document:
                    data['document_link'] = (
                        IContentListingObject(document).render_link())
                    data.update(
                        self._get_edit_document_options(
                            document, item, meeting))

                data['excerpts'] = self._serialize_excerpts(meeting, item)
                if item.can_generate_excerpt():
                    data['generate_excerpt_default_title'] = translate(
                        _(u'excerpt_document_default_title',
                          default=u'Excerpt ${title}',
                          mapping={'title': safe_unicode(item.get_title())}),
                        context=self.request,
                    ).strip()
                    data['generate_excerpt_link'] = meeting.get_url(
                        view='agenda_items/{}/generate_excerpt'.format(
                            item.agenda_item_id))

                if item.is_decided():
                    data['css_class'] += ' decided'

            agenda_items.append(data)
        return agenda_items
Ejemplo n.º 25
0
    def createAndAdd(self, data):
        if not is_word_meeting_implementation_enabled():
            return super(AddForm, self).createAndAdd(data)

        proposal_template = data.pop('proposal_template')
        edit_after_creation = data.pop('edit_after_creation')
        self.instance_schema = IProposal
        noaq_proposal = super(AddForm, self).createAndAdd(data)
        proposal = self.context.get(noaq_proposal.getId())
        proposal_doc = proposal.create_proposal_document(
            proposal_template.file)
        if edit_after_creation:
            self.checkout_and_external_edit(proposal_doc)
        return proposal
Ejemplo n.º 26
0
    def after_create(self, obj):
        obj.create_model(self.model_arguments, self.container)

        if is_word_meeting_implementation_enabled():
            obj.create_proposal_document(
                filename=u'proposal_document.docx',
                data=self._proposal_file_data,
                content_type='application/vnd.openxmlformats'
                '-officedocument.wordprocessingml.document')

        if self._transition:
            obj.execute_transition(self._transition)

        super(ProposalBuilder, self).after_create(obj)
Ejemplo n.º 27
0
    def revise(self, agenda_item):
        assert self.get_state() == self.STATE_DECIDED
        if is_word_meeting_implementation_enabled():
            document = self.resolve_submitted_proposal().get_proposal_document(
            )
            checkout_manager = getMultiAdapter((document, document.REQUEST),
                                               ICheckinCheckoutManager)
            if checkout_manager.get_checked_out_by() is not None:
                raise ValueError(
                    'Cannot revise proposal when proposal document is checked out.'
                )
        else:
            self.update_excerpt(agenda_item)

        IHistory(self.resolve_submitted_proposal()).append_record(u'revised')
Ejemplo n.º 28
0
    def decide(self, agenda_item):
        if is_word_meeting_implementation_enabled():
            document = self.resolve_submitted_proposal().get_proposal_document(
            )
            checkout_manager = getMultiAdapter((document, document.REQUEST),
                                               ICheckinCheckoutManager)
            if checkout_manager.get_checked_out_by() is not None:
                raise ValueError(
                    'Cannot decide proposal when proposal document is checked out.'
                )
        else:
            self.generate_excerpt(agenda_item)
            document_intid = self.copy_excerpt_to_proposal_dossier()
            self.register_excerpt(document_intid)

        IHistory(self.resolve_submitted_proposal()).append_record(u'decided')
        self.execute_transition('scheduled-decided')
Ejemplo n.º 29
0
    def bodyClass(self, template, view):
        """Extends the default body class with the `feature-bumblebee` class, if
        the bumblebeefeature is enabled.
        """
        classes = [super(GeverLayoutPolicy, self).bodyClass(template, view)]

        if is_bumblebee_feature_enabled():
            classes.append('feature-bumblebee')

        if is_word_meeting_implementation_enabled():
            classes.append('feature-word-meeting')

        if ISQLObjectWrapper.providedBy(self.context):
            normalize = getUtility(IIDNormalizer).normalize
            classes.append('model-{}'.format(
                normalize(type(self.context.model).__name__)))

        return ' '.join(classes)
Ejemplo n.º 30
0
    def render(self):
        jsondata = self.request.get(REQUEST_KEY)
        data = json.loads(jsondata)
        committee = Oguid.parse(data['committee_oguid']).resolve_object()
        proposal_oguid = Oguid.parse(data['proposal_oguid'])
        proposal = meeting_service().fetch_proposal_by_oguid(proposal_oguid)

        with elevated_privileges():
            submitted_proposal = SubmittedProposal.create(proposal, committee)

            if is_word_meeting_implementation_enabled():
                submitted_proposal.create_proposal_document(
                    filename=data['file']['filename'],
                    content_type=data['file']['contentType'].encode('utf-8'),
                    data=base64.decodestring(data['file']['data']))

            self.request.response.setHeader("Content-type", "application/json")
            return json.dumps(
                {'path': '/'.join(submitted_proposal.getPhysicalPath())})