def test_multi_admin_unit_team_task_edit_in_issuer_dossier(self, browser):
        self.login(self.regular_user, browser=browser)

        ra_admin_unit = create(Builder('admin_unit')
                                .having(title=u'Ratskanzlei',
                                        unit_id=u'rk',
                                        public_url='http://nohost/plone'))

        create(Builder('org_unit')
               .id('rk')
               .having(title=u'Ratskanzlei', admin_unit=ra_admin_unit)
               .with_default_groups())

        ITask(self.task).responsible = u'team:1'
        ITask(self.task).responsible_client = u'rk'
        self.task.get_sql_object().responsible = u'team:1'
        self.task.get_sql_object().assigned_org_unit = u'rk'

        self.set_workflow_state('task-state-open', self.task)

        browser.open(self.task)
        browser.click_on('task-transition-open-in-progress')
        browser.fill({'Accept the task and ...': 'participate'})
        browser.click_on('Continue')

        self.assertEquals(self.regular_user.getId(), self.task.responsible)
        self.assertEquals(self.regular_user.getId(),
                          self.task.get_sql_object().responsible)
Example #2
0
def create_subtask_response(context, event):
    """When adding a new task object within a task(subtask),
    it adds a response to the maintask.
    """

    # the event is fired multiple times when the task was transported, so we
    # need to verify that the request was not called by another client.
    request = context.REQUEST
    if request.get_header('X-OGDS-AC', None) or \
            request.get_header('X-OGDS-AUID', None) or \
            request.get('X-CREATING-SUCCESSOR', None):
        return

    parent = aq_parent(aq_inner(context))
    if ITask.providedBy(parent):
        if ITask.providedBy(context):
            transition = 'transition-add-subtask'

            # If the the added object is a subtask we have to make sure
            # that the subtask is already synced to the globalindex
            if not context.get_sql_object():
                TaskSqlSyncer(context, event).sync()

        elif IBaseDocument.providedBy(context):
            transition = 'transition-add-document'

        # add a response with a link to the object
        add_simple_response(parent, added_object=context,
                            transition=transition)
Example #3
0
    def _update(self, transition, text):
        response = super(WorkflowResponseSyncerReceiver,
                         self)._update(transition, text)

        transition = self.request.get('transition')
        responsible = self.request.get('responsible')
        responsible_client = self.request.get('responsible_client')

        wftool = getToolByName(self.context, 'portal_workflow')

        # change workflow state
        before = wftool.getInfoFor(self.context, 'review_state')
        before = wftool.getTitleForStateOnType(before, self.context.Type())

        with elevated_privileges():
            wftool.doActionFor(self.context, transition)

        after = wftool.getInfoFor(self.context, 'review_state')
        after = wftool.getTitleForStateOnType(after, self.context.Type())

        if responsible and responsible is not 'None':
            # special handling for reassign
            response.add_change(
                'responsible', _(u"label_responsible", default=u"Responsible"),
                ITask(self.context).responsible, responsible)

            ITask(self.context).responsible_client = responsible_client
            ITask(self.context).responsible = responsible

        notify(ObjectModifiedEvent(self.context))
        response.add_change('review_state', _(u'Issue state'), before, after)
Example #4
0
def create_subtask_response(context, event):
    """When adding a new task object within a task(subtask),
    it adds a response to the maintask.
    """

    # the event is fired multiple times when the task was transported, so we
    # need to verify that the request was not called by another client.
    request = context.REQUEST
    if request.get_header('X-OGDS-AC', None) or \
            request.get_header('X-OGDS-AUID', None) or \
            request.get('X-CREATING-SUCCESSOR', None):
        return

    parent = aq_parent(aq_inner(context))
    if ITask.providedBy(parent):
        if ITask.providedBy(context):
            transition = 'transition-add-subtask'

            # If the the added object is a subtask we have to make sure
            # that the subtask is already synced to the globalindex
            if not context.get_sql_object():
                TaskSqlSyncer(context, event).sync()

        elif IBaseDocument.providedBy(context):
            transition = 'transition-add-document'

        # add a response with a link to the object
        add_simple_response(parent,
                            added_object=context,
                            transition=transition)
    def create_successor_task(self, dossier):
        # we need all task field values from the forwarding
        fielddata = {}
        for fieldname in ITask.names():
            value = ITask.get(fieldname).get(self.context)
            fielddata[fieldname] = value

        # Reset issuer to the current inbox
        fielddata['issuer'] = get_current_org_unit().inbox().id()

        # Predefine the task_type to avoid tasks with an invalid task_type
        fielddata['task_type'] = FORWARDING_SUCCESSOR_TYPE

        # lets create a new task - the successor task
        task = createContentInContainer(
            dossier, 'opengever.task.task', **fielddata)

        # Add issuer and responsible to the watchers of the newly created task
        center = notification_center()
        center.add_task_responsible(task, task.responsible)
        center.add_task_issuer(task, task.issuer)

        # copy documents and map the intids
        intids_mapping = _copy_documents_from_forwarding(self.context, task)

        # copy the responses
        response_transporter = IResponseTransporter(task)
        response_transporter.get_responses(
            get_current_admin_unit().id(),
            '/'.join(self.context.getPhysicalPath()),
            intids_mapping=intids_mapping)

        return task
 def reassign_team_task(self, response):
     old_responsible = ITask(self.context).responsible
     ITask(self.context).responsible = api.user.get_current().getId()
     response.add_change(
         'responsible',
         old_responsible, ITask(self.context).responsible,
         _(u"label_responsible", default=u"Responsible"))
     self.context.sync()
Example #7
0
def reassign_team_tasks(task, event):
    if event.action != 'task-transition-open-in-progress':
        return

    if task.is_team_task:
        old_responsible = ITask(task).responsible
        ITask(task).responsible = api.user.get_current().getId()
        IResponseContainer(task)[-1].add_change(
            'responsible', _(u"label_responsible", default=u"Responsible"),
            old_responsible,
            ITask(task).responsible)
Example #8
0
def assign_forwarding_to_dossier(
        context, forwarding_oguid, dossier, response_text):

    forwarding = Task.query.by_oguid(forwarding_oguid)

    forwarding_obj = context.unrestrictedTraverse(
        forwarding.physical_path.encode('utf-8'))

    # we need all task field values from the forwarding
    fielddata = {}
    for fieldname in ITask.names():
        value = ITask.get(fieldname).get(forwarding_obj)
        fielddata[fieldname] = value

    # Reset issuer to the current inbox
    fielddata['issuer'] = get_current_org_unit().inbox().id()

    # Predefine the task_type to avoid tasks with an invalid task_type
    fielddata['task_type'] = FORWARDING_SUCCESSOR_TYPE

    # lets create a new task - the successor task
    task = createContentInContainer(
        dossier, 'opengever.task.task', **fielddata)

    successor_tc_task = ISuccessorTaskController(task)

    # Add issuer and responsible to the watchers of the newly created task
    center = notification_center()
    center.add_task_responsible(task, task.responsible)
    center.add_task_issuer(task, task.issuer)

    # copy documents and map the intids
    intids_mapping = _copy_documents_from_forwarding(forwarding_obj, task)

    # copy the responses
    response_transporter = IResponseTransporter(task)
    response_transporter.get_responses(
        get_current_admin_unit().id(),
        '/'.join(forwarding_obj.getPhysicalPath()),
        intids_mapping=intids_mapping)

    # close and store the forwarding in yearfolder
    change_task_workflow_state(
        forwarding_obj,
        'forwarding-transition-assign-to-dossier',
        text=response_text,
        successor_oguid=successor_tc_task.get_oguid())

    IYearfolderStorer(forwarding_obj).store_in_yearfolder()

    # successor
    successor_tc_task.set_predecessor(forwarding_oguid)

    return task
Example #9
0
def assign_forwarding_to_dossier(context, forwarding_oguid, dossier,
                                 response_text):

    forwarding = Task.query.by_oguid(forwarding_oguid)

    forwarding_obj = context.unrestrictedTraverse(
        forwarding.physical_path.encode('utf-8'))

    # we need all task field values from the forwarding
    fielddata = {}
    for fieldname in ITask.names():
        value = ITask.get(fieldname).get(forwarding_obj)
        fielddata[fieldname] = value

    # Reset issuer to the current inbox
    fielddata['issuer'] = get_current_org_unit().inbox().id()

    # Predefine the task_type to avoid tasks with an invalid task_type
    fielddata['task_type'] = FORWARDING_SUCCESSOR_TYPE

    # lets create a new task - the successor task
    task = createContentInContainer(dossier, 'opengever.task.task',
                                    **fielddata)

    successor_tc_task = ISuccessorTaskController(task)

    # Add issuer and responsible to the watchers of the newly created task
    center = notification_center()
    center.add_task_responsible(task, task.responsible)
    center.add_task_issuer(task, task.issuer)

    # copy documents and map the intids
    intids_mapping = _copy_documents_from_forwarding(forwarding_obj, task)

    # copy the responses
    response_transporter = IResponseTransporter(task)
    response_transporter.get_responses(get_current_admin_unit().id(),
                                       '/'.join(
                                           forwarding_obj.getPhysicalPath()),
                                       intids_mapping=intids_mapping)

    # close and store the forwarding in yearfolder
    change_task_workflow_state(forwarding_obj,
                               'forwarding-transition-assign-to-dossier',
                               text=response_text,
                               successor_oguid=successor_tc_task.get_oguid())

    IYearfolderStorer(forwarding_obj).store_in_yearfolder()

    # successor
    successor_tc_task.set_predecessor(forwarding_oguid)

    return task
Example #10
0
    def render(self):

        if not IInternalOpengeverRequestLayer.providedBy(self.request):
            raise Forbidden()

        transition = self.request.get('transition')
        text = self.request.get('text')
        responsible = self.request.get('responsible')
        responsible_client = self.request.get('responsible_client')

        if self.is_already_done(transition, text):
            # Set correct content type for text response
            self.request.response.setHeader("Content-type", "text/plain")

            return 'OK'

        wftool = getToolByName(self.context, 'portal_workflow')

        # change workflow state
        before = wftool.getInfoFor(self.context, 'review_state')
        before = wftool.getTitleForStateOnType(before, self.context.Type())

        wftool.doActionFor(self.context, transition)

        after = wftool.getInfoFor(self.context, 'review_state')
        after = wftool.getTitleForStateOnType(after, self.context.Type())

        # create response
        response = add_simple_response(
            self.context,
            transition=transition,
            text=text)

        if responsible and responsible is not 'None':
            # special handling for reassign
            response.add_change(
                'reponsible',
                _(u"label_responsible", default=u"Responsible"),
                ITask(self.context).responsible,
                responsible)

            ITask(self.context).responsible_client = responsible_client
            ITask(self.context).responsible = responsible

            notify(ObjectModifiedEvent(self.context))

        response.add_change('review_state', _(u'Issue state'),
                            before, after)

        # Set correct content type for text response
        self.request.response.setHeader("Content-type", "text/plain")

        return 'OK'
    def after_transition_hook(self, transition, disable_sync, transition_params):
        self.update_watchers()

        response = add_simple_response(
            self.context, transition=transition, text=transition_params.get('text'))

        response.add_change(
            'responsible',
            ITask(self.context).responsible, ITask(self.context).issuer,
            _(u"label_responsible", default=u"Responsible"))

        self.save_related_items(response, transition_params.get('relatedItems'))
        self.switch_responsible()
    def save_related_items(self, response, related_items):
        if not related_items:
            return

        intids = getUtility(IIntIds)
        current_ids = [item.to_id for item in ITask(self.context).relatedItems]
        for item in related_items:
            to_id = intids.getId(item)
            item._v__is_relation = True
            if to_id not in current_ids:
                ITask(self.context).relatedItems.append(RelationValue(to_id))
                response.add_change(
                    'relatedItems',
                    '', item.title,
                    _(u'label_related_items', default=u"Related Items"))
Example #13
0
 def get_containing_task(self):
     """ Get the parent-tasks if we have one
     """
     parent = aq_parent(aq_inner(self.context))
     if ITask.providedBy(parent):
         return parent.get_sql_object()
     return None
    def test_only_team_members_count_as_responsible(self, browser):
        self.login(self.regular_user, browser)

        ITask(self.task).responsible = u'team:2'
        self.task.get_sql_object().responsible = u'team:2'
        self.set_workflow_state('task-state-open', self.task)

        browser.open(self.task, view='tabbedview_view-overview')
        self.assertEquals(
            ['task-transition-reassign', 'label_add_comment'],
            browser.css('.actionButtons li').text,
            'Expect none responsible actions, because the regular_user is not '
            'a team member and therefore not a responsible.')

        self.login(self.meeting_user, browser)
        browser.open(self.task, view='tabbedview_view-overview')
        self.assertEquals(
            [
                'task-transition-open-in-progress',
                'task-transition-open-rejected',
                'task-transition-open-resolved', 'task-transition-reassign',
                'label_add_comment'
            ],
            browser.css('.actionButtons li').text,
            'Expect responsible actions, because the meeting_user is a team '
            'member and therefore not a responsible.')
Example #15
0
    def _set_immediate_view(self, created):
        """The default behavior implemented by the dexterity add form is
        circumvented by this form. If there's only one task the immediate_view
        of the task fti is respected. If there is more than one task, a
        differen TaskRedirector implementation is used."""

        if len(created) == 1:
            task = created[0]
            fti = getUtility(IDexterityFTI, name=self.portal_type)
            if fti.immediate_view:
                self.immediate_view = "{0}/{1}/{2}".format(
                    self.context.absolute_url(),
                    task.id,
                    fti.immediate_view,
                )
            else:
                self.immediate_view = "{0}/{1}".format(
                    self.context.absolute_url(), task.id)
        else:
            if ITask.providedBy(self.context):
                redirect_to = '{0}#overview'.format(
                    self.context.absolute_url())
            else:
                redirect_to = '{0}#tasks'.format(self.context.absolute_url())

            self.immediate_view = redirect_to
Example #16
0
 def get_containing_task(self):
     """ Get the parent-tasks if we have one
     """
     parent = aq_parent(aq_inner(self.context))
     if ITask.providedBy(parent):
         return parent.get_sql_object()
     return None
Example #17
0
    def get_added_objects(self):
        """ Returns two lists of docs, subtasks
        """
        try:
            self.added_object
        except AttributeError:
            return [], []

        # .. and sometimes it may be empty.
        if not self.added_object:
            return [], []

        # Support for multiple added objects
        if hasattr(self.added_object, '__iter__'):
            relations = self.added_object
        else:
            relations = [self.added_object]

        docs = []
        subtasks = []
        for rel in relations:
            obj = rel.to_object
            if ITask.providedBy(obj):
                subtasks.append(obj)
            else:
                docs.append(obj)

        return docs, subtasks
Example #18
0
def get_redirect_url(context):
        """return the url where the editing_document view was called from
        It should be a document listing."""

        referer = context.REQUEST.environ.get('HTTP_REFERER')
        portal_url = '/'.join(context.portal_url().split('/')[:-1])
        if referer:
            obj_path = referer[len(portal_url):]
            try:
                obj = context.restrictedTraverse(obj_path)
            except KeyError:
                return  '%s#overview' % context.absolute_url()

            # redirect to right tabbedview-tab
            if ITask.providedBy(obj):
                return '%s#relateddocuments' % (obj.absolute_url())
            elif IPloneSiteRoot.providedBy(obj):
                return '%s#mydocuments' % (obj.absolute_url())
            elif IDossierMarker.providedBy(obj):
                return '%s#documents' % (obj.absolute_url())
            else:
                return obj.absolute_url()

        else:
            return  '%s#overview' % context.absolute_url()
Example #19
0
    def createAndAdd(self, data):
        created = []

        # make sure we don't create private tasks when the feature is
        # not enabled. the field is hidden, but users could still submit.
        if not is_private_task_feature_enabled():
            data['is_private'] = False

        if isinstance(data['responsible'], basestring):
            data['responsible'] = [data['responsible']]

        all_responsible_users = data['responsible']
        for responsible in all_responsible_users:
            data['responsible'] = responsible
            update_reponsible_field_data(data)
            created.append(self._create_task(data))

        # Restore responsible in data
        data['responsible'] = all_responsible_users

        # Set tasktemplate order and move to planned state if it's part
        # of a sequential process
        if ITask.providedBy(
                self.context) and self.context.is_sequential_main_task():
            position = data['tasktemplate_position']
            if not position:
                position = len(self.context.get_tasktemplate_order())

            for task in created:
                self.context.add_task_to_tasktemplate_order(position, task)

        self._set_immediate_view(created)
        return created
Example #20
0
    def test_responsible_change_is_visible_in_the_response(self, browser):
        self.login(self.regular_user, browser)

        ITask(self.task).responsible = u'team:1'
        self.task.get_sql_object().responsible = u'team:1'
        self.set_workflow_state('task-state-open', self.task)

        browser.open(self.task, view='tabbedview_view-overview')
        browser.click_on('task-transition-open-in-progress')
        browser.fill({'Response': u'Das \xfcbernehme ich!'})
        browser.click_on('Save')

        response = IResponseContainer(self.task).list()[-1]
        expected = [{
            'before': u'team:1',
            'after': 'kathi.barfuss',
            'field_id': 'responsible',
            'field_title': u'label_responsible'
        }]

        self.assertEqual(expected,
                         [dict(change) for change in response.changes])

        browser.open(self.task, view='tabbedview_view-overview')
        self.assertEqual(
            u'Accepted by B\xe4rfuss K\xe4thi (kathi.barfuss), responsible '
            u'changed from Projekt \xdcberbaung Dorfmatte (Finanz\xe4mt) to '
            u'B\xe4rfuss K\xe4thi (kathi.barfuss).',
            browser.css('.answer h3').text[0])
Example #21
0
    def get_added_objects(self):
        """ Returns two lists of docs, subtasks
        """
        try:
            self.added_object
        except AttributeError:
            return [], []

        # .. and sometimes it may be empty.
        if not self.added_object:
            return [], []

        # Support for multiple added objects
        if hasattr(self.added_object, '__iter__'):
            relations = self.added_object
        else:
            relations = [self.added_object]

        docs = []
        subtasks = []
        for rel in relations:
            obj = rel.to_object
            if ITask.providedBy(obj):
                subtasks.append(obj)
            else:
                docs.append(obj)

        return docs, subtasks
Example #22
0
 def get_containing_task(self):
     """ Get the parent-tasks if we have one
     """
     parent = aq_parent(aq_inner(self.context))
     if ITask.providedBy(parent):
         return [parent]
     return []
Example #23
0
def get_redirect_url(context):
    """return the url where the editing_document view was called from
        It should be a document listing."""

    referer = context.REQUEST.environ.get('HTTP_REFERER')
    portal_url = '/'.join(context.portal_url().split('/')[:-1])
    if referer:
        obj_path = referer[len(portal_url):]
        try:
            obj = context.restrictedTraverse(obj_path)
        except KeyError:
            return '%s#overview' % context.absolute_url()

        # redirect to right tabbedview-tab
        if ITask.providedBy(obj):
            return '%s#relateddocuments' % (obj.absolute_url())
        elif IPloneSiteRoot.providedBy(obj):
            return '%s#mydocuments' % (obj.absolute_url())
        elif IDossierMarker.providedBy(obj):
            return '%s#documents' % (obj.absolute_url())
        else:
            return obj.absolute_url()

    else:
        return '%s#overview' % context.absolute_url()
Example #24
0
    def test_revokes_permissions_on_proposal(self):
        self.login(self.dossier_responsible)

        intids = getUtility(IIntIds)
        relation = RelationValue(intids.getId(self.proposaldocument))
        ITask(self.subtask).relatedItems.append(relation)
        notify(ObjectModifiedEvent(self.subtask))

        self.set_workflow_state('task-state-tested-and-closed', self.subtask)

        expected_assignments = [{
            'cause': ASSIGNMENT_VIA_TASK,
            'roles': ['Reader', 'Editor'],
            'reference': Oguid.for_object(self.subtask),
            'principal': self.regular_user.id
        }, {
            'cause': ASSIGNMENT_VIA_TASK_AGENCY,
            'roles': ['Reader', 'Editor'],
            'reference': Oguid.for_object(self.subtask),
            'principal': u'fa_inbox_users'
        }]

        document_storage = RoleAssignmentManager(self.proposaldocument).storage
        self.assertEqual(expected_assignments, document_storage._storage())

        proposal_storage = RoleAssignmentManager(self.proposal).storage
        self.assertEqual(expected_assignments, proposal_storage._storage())

        RevokePermissions(self.subtask, self.request)()
        self.assertEqual([], proposal_storage._storage())
        self.assertEqual([], document_storage._storage())
Example #25
0
 def get_containing_task(self):
     """ Get the parent-tasks if we have one
     """
     parent = aq_parent(aq_inner(self.context))
     if ITask.providedBy(parent):
         return [parent]
     return []
Example #26
0
def assign_forwarding_to_dossier(
    context, forwarding_oguid, dossier, response_text):

    forwarding = getUtility(ITaskQuery).get_task_by_oguid(forwarding_oguid)

    forwarding_obj = context.unrestrictedTraverse(
        forwarding.physical_path.encode('utf-8'))

    # we need all task field values from the forwarding
    fielddata = {}
    for fieldname in ITask.names():
        value = ITask.get(fieldname).get(forwarding_obj)
        fielddata[fieldname] = value

    # lets create a new task - the successor task
    task = createContentInContainer(
        dossier, 'opengever.task.task', **fielddata)

    successor_tc_task = ISuccessorTaskController(task)

    # copy documents and map the intids
    intids_mapping = _copy_documents_from_forwarding(forwarding_obj, task)

    # copy the responses
    response_transporter = IResponseTransporter(task)
    response_transporter.get_responses(
        get_client_id(),
        '/'.join(forwarding_obj.getPhysicalPath()),
        intids_mapping=intids_mapping)

    # close and store the forwarding in yearfolder
    change_task_workflow_state(
        forwarding_obj,
        'forwarding-transition-assign-to-dossier',
        text=response_text,
        successor_oguid=successor_tc_task.get_oguid())

    inbox = aq_parent(aq_inner(forwarding_obj))
    yearfolder = _get_yearfolder(inbox)
    clipboard = inbox.manage_cutObjects((forwarding_obj.getId(),))
    yearfolder.manage_pasteObjects(clipboard)

    # successor
    successor_tc_task.set_predecessor(forwarding_oguid)

    return task
Example #27
0
    def render(self):
        parent = aq_inner(aq_parent(self.context))
        if ITask.providedBy(parent):
            redirect_to = '%s#overview' % parent.absolute_url()
        else:
            redirect_to = '%s#tasks' % parent.absolute_url()

        return self.request.RESPONSE.redirect(redirect_to)
    def test_set_current_user_as_responsible_when_accepting_a_team_task(self, browser):
        self.login(self.regular_user, browser)

        ITask(self.task).responsible = u'team:1'
        self.task.get_sql_object().responsible = u'team:1'
        self.set_workflow_state('task-state-open', self.task)

        browser.open(self.task, view='tabbedview_view-overview')

        browser.click_on('task-transition-open-in-progress')
        browser.fill({'Response': u'Das \xfcbernehme ich!'})
        browser.click_on('Save')

        self.assertEquals(self.regular_user.getId(),
                          ITask(self.task).responsible)
        self.assertEquals(self.regular_user.getId(),
                          self.task.get_sql_object().responsible)
Example #29
0
    def render(self):
        parent = aq_inner(aq_parent(self.context))
        if ITask.providedBy(parent):
            redirect_to = '%s#overview' % parent.absolute_url()
        else:
            redirect_to = '%s#tasks' % parent.absolute_url()

        return self.request.RESPONSE.redirect(redirect_to)
    def reindex_dossier_and_children(self, dossier):
        children = self.catalog(path='/'.join(dossier.getPhysicalPath()))
        for child in children:
            obj = child.getObject()
            obj.reindexObject(idxs=['reference'])

            if ITask.providedBy(obj):
                obj.get_sql_object().sync_with(obj)
Example #31
0
def assign_forwarding_to_dossier(context, forwarding_oguid, dossier,
                                 response_text):

    forwarding = getUtility(ITaskQuery).get_task_by_oguid(forwarding_oguid)

    forwarding_obj = context.unrestrictedTraverse(
        forwarding.physical_path.encode('utf-8'))

    # we need all task field values from the forwarding
    fielddata = {}
    for fieldname in ITask.names():
        value = ITask.get(fieldname).get(forwarding_obj)
        fielddata[fieldname] = value

    # lets create a new task - the successor task
    task = createContentInContainer(dossier, 'opengever.task.task',
                                    **fielddata)

    successor_tc_task = ISuccessorTaskController(task)

    # copy documents and map the intids
    intids_mapping = _copy_documents_from_forwarding(forwarding_obj, task)

    # copy the responses
    response_transporter = IResponseTransporter(task)
    response_transporter.get_responses(get_client_id(),
                                       '/'.join(
                                           forwarding_obj.getPhysicalPath()),
                                       intids_mapping=intids_mapping)

    # close and store the forwarding in yearfolder
    change_task_workflow_state(forwarding_obj,
                               'forwarding-transition-assign-to-dossier',
                               text=response_text,
                               successor_oguid=successor_tc_task.get_oguid())

    inbox = aq_parent(aq_inner(forwarding_obj))
    yearfolder = _get_yearfolder(inbox)
    clipboard = inbox.manage_cutObjects((forwarding_obj.getId(), ))
    yearfolder.manage_pasteObjects(clipboard)

    # successor
    successor_tc_task.set_predecessor(forwarding_oguid)

    return task
Example #32
0
def reindex_containing_dossier_for_contained_objects(dossier, event):
    """Reindex the containging_dossier index for all the contained obects.
    """
    for brain in dossier.portal_catalog(path='/'.join(dossier.getPhysicalPath())):
        obj = brain.getObject()
        obj.reindexObject(idxs=['containing_dossier'])

        if ITask.providedBy(obj):
            sync_task(brain.getObject(), event)
Example #33
0
def object_moved_or_added(context, event):
    if isinstance(event, ObjectAddedEvent):
        # Don't consider moving or removing an object a "touch". Mass-moves
        # would immediately fill up the touched log, and removals should not
        # be tracked anyway.
        if should_track_touches(context):
            notify(ObjectTouchedEvent(context))

        # If an object has been copy & pasted, we need to reindex some fields.
        # The IObjectCopiedEvent is too early to do that though, because at
        # that point the object doesn't have a full AQ chain yet. We therefore
        # just mark it during IObjectCopiedEvent, and do the reindexing here.
        if getattr(context, '_v_object_has_been_copied', False):
            context.reindexObject(idxs=reindex_after_copy)

    if IObjectRemovedEvent.providedBy(event):
        return

    # Update object security after moving or copying.
    # Specifically, this is needed for the case where an object is moved out
    # of a location where a Placeful Workflow Policy applies to a location
    # where it doesn't.
    #
    #  Plone then no longer provides the placeful workflow for that object,
    # but doesn't automatically update the object's security.
    #
    # We use ftw.upgrade's update_security_for() here to correctly
    # recalculate security, but do the reindexing ourselves because otherwise
    # Plone will do it recursively (unnecessarily so).
    changed = update_security_for(context, reindex_security=False)
    if changed:
        reindex_object_security_without_children(context)

    # There are several indices that need updating when a dossier is moved.
    # first make sure obj was actually moved and not created
    if not event.oldParent or not event.newParent:
        return

    # When an object is moved, its containing_dossier needs reindexing.
    to_reindex = ['containing_dossier']
    # containing_subdossier is really only used for documents,
    # while is_subdossier is only meaningful for dossiers.
    if IDossierMarker.providedBy(context):
        was_subdossier = IDossierMarker.providedBy(event.oldParent)
        is_subdossier = IDossierMarker.providedBy(event.newParent)
        if was_subdossier != is_subdossier:
            to_reindex.append('is_subdossier')

    if context.portal_type in TYPES_WITH_CONTAINING_SUBDOSSIER_INDEX:
        to_reindex.append('containing_subdossier')

    context.reindexObject(idxs=to_reindex)

    # synchronize with model if necessary
    if ITask.providedBy(context):
        sync_task(context, event)
Example #34
0
def reindex_containing_dossier_for_contained_objects(dossier, event):
    """Reindex the containging_dossier index for all the contained obects.
    """
    for brain in dossier.portal_catalog(
            path='/'.join(dossier.getPhysicalPath())):
        obj = brain.getObject()
        obj.reindexObject(idxs=['containing_dossier'])

        if ITask.providedBy(obj):
            sync_task(brain.getObject(), event)
Example #35
0
 def get_type(self, item):
     """differ the object typ and return the type as string
     """
     if not item:
         return None
     elif isinstance(item, dict):
         return 'dict'
     elif isinstance(item, Task) or ITask.providedBy(item):
         return 'task'
     else:
         return 'obj'
Example #36
0
    def test_multi_admin_unit_team_task_edit_in_issuer_dossier(self, browser):
        self.login(self.regular_user, browser=browser)

        self.add_additional_admin_and_org_unit()

        ITask(self.task).responsible = u'team:1'
        ITask(self.task).responsible_client = u'gdgs'
        self.task.get_sql_object().responsible = u'team:1'
        self.task.get_sql_object().assigned_org_unit = u'gdgs'

        self.set_workflow_state('task-state-open', self.task)

        browser.open(self.task)
        browser.click_on('task-transition-open-in-progress')
        browser.fill({'Accept the task and ...': 'participate'})
        browser.click_on('Continue')

        self.assertEquals(self.regular_user.getId(), self.task.responsible)
        self.assertEquals(self.regular_user.getId(),
                          self.task.get_sql_object().responsible)
Example #37
0
 def get_type(self, item):
     """differ the object typ and return the type as string
     """
     if not item:
         return None
     elif isinstance(item, dict):
         return "dict"
     elif isinstance(item, Task) or ITask.providedBy(item):
         return "task"
     else:
         return "obj"
Example #38
0
def update_deadline(task, event):
    """Update the parents deadline, when a subtask deadline has changed."""
    for descr in event.descriptions:
        for attr in descr.attributes:
            if attr == 'deadline':
                parent = aq_parent(aq_inner(task))
                if ITask.providedBy(parent):
                    temp = task.deadline + timedelta(MAIN_TASK_DEADLINE_DELTA)
                    if parent.deadline < temp:
                        parent.deadline = temp
                        parent.reindexObject()
Example #39
0
def _get_task_css_class(task):
    """A task helper function for `get_css_class`, providing some metadata
    of a task. The task may be a brain, a dexterity object or a sql alchemy
    globalindex object.
    """
    if ICatalogBrain.providedBy(task) or ISolrDocument.providedBy(task):
        task = Task.query.by_brain(task)

    if ITask.providedBy(task):
        task = task.get_sql_object()

    return task.get_css_class()
Example #40
0
def set_initial_state(task, event):
    """When adding a subtask to a sequential task process, the new task should
    be in the planned state.
    """
    if IDuringTaskTemplateFolderTriggering.providedBy(getRequest()):
        return

    parent = aq_parent(aq_inner(task))
    if ITask.providedBy(parent) \
       and IFromSequentialTasktemplate.providedBy(parent):

        task.set_to_planned_state()
Example #41
0
 def _task_state_wrapper(self, item, text):
     """ Wrap a span-tag around the text with the status-css class
     """
     if isinstance(item, Task):
         # Its a sql-task-object
         state = item.review_state
     elif ITask.providedBy(item):
         # Its a task-object
         state = getToolByName(self.context, "portal_workflow").getInfoFor(item, "review_state")
     else:
         return ""
     return '<span class="wf-%s">%s</span>' % (state, text)
Example #42
0
def _get_task_css_class(task):
    """A task helper function for `get_css_class`, providing some metadata
    of a task. The task may be a brain, a dexterity object or a sql alchemy
    globalindex object.
    """
    if ICatalogBrain.providedBy(task) or ISolrDocument.providedBy(task):
        task = Task.query.by_brain(task)

    if ITask.providedBy(task):
        task = task.get_sql_object()

    return task.get_css_class()
Example #43
0
def set_initial_state(task, event):
    """When adding a subtask to a sequential task process, the new task should
    be in the planned state.
    """
    if IDuringTaskTemplateFolderTriggering.providedBy(getRequest()):
        return

    parent = aq_parent(aq_inner(task))
    if ITask.providedBy(parent) \
       and parent.is_sequential_main_task():

        task.set_to_planned_state()
Example #44
0
def update_deadline(task, event):
    """Update the parents deadline, when a subtask deadline has changed."""
    for descr in event.descriptions:
        for attr in descr.attributes:
            if attr == 'deadline':
                parent = aq_parent(aq_inner(task))
                if ITask.providedBy(parent):
                    offset = api.portal.get_registry_record(
                        'deadline_timedelta', interface=ITaskSettings)
                    temp = task.deadline + timedelta(offset)
                    if parent.deadline < temp:
                        parent.deadline = temp
                        parent.reindexObject()
Example #45
0
    def render_task(self, item):
        """ Render the taskobject
        """
        if isinstance(item, Task):
            # Its a task stored in sql
            return self._sqlalchemy_task_link(item)

        elif ITask.providedBy(item):
            # Its a normal task object
            return self._object_task_link(item)

        else:
            return None
 def is_available(self):
     """The action should only be available on closed tasks for
     administrators and task issuer and only if the feature is enabled.
     """
     if not is_optional_task_permissions_revoking_enabled():
         return False
     if not ITask.providedBy(self.context):
         return False
     if not self.context.get_review_state() in FINAL_TASK_STATES:
         return False
     if api.user.has_permission('cmf.ManagePortal'):
         return True
     issuer = self.context.get_issuer_actor()
     return issuer.identifier == api.user.get_current().id
Example #47
0
def object_moved_or_added(context, event):
    if isinstance(event, ObjectAddedEvent):
        # Don't consider moving or removing an object a "touch". Mass-moves
        # would immediately fill up the touched log, and removals should not
        # be tracked anyway.
        if should_track_touches(context):
            notify(ObjectTouchedEvent(context))

    if IObjectRemovedEvent.providedBy(event):
        return

    # Update object security after moving or copying.
    # Specifically, this is needed for the case where an object is moved out
    # of a location where a Placeful Workflow Policy applies to a location
    # where it doesn't.
    #
    #  Plone then no longer provides the placeful workflow for that object,
    # but doesn't automatically update the object's security.
    #
    # We use ftw.upgrade's update_security_for() here to correctly
    # recalculate security, but do the reindexing ourselves because otherwise
    # Plone will do it recursively (unnecessarily so).
    changed = update_security_for(context, reindex_security=False)
    if changed:
        reindex_object_security_without_children(context)

    # There are several indices that need updating when a dossier is moved.
    # first make sure obj was actually moved and not created
    if not event.oldParent or not event.newParent:
        return

    # When an object is moved, its containing_dossier needs reindexing.
    to_reindex = ['containing_dossier']
    # containing_subdossier is really only used for documents,
    # while is_subdossier is only meaningful for dossiers.
    if IDossierMarker.providedBy(context):
        was_subdossier = IDossierMarker.providedBy(event.oldParent)
        is_subdossier = IDossierMarker.providedBy(event.newParent)
        if was_subdossier != is_subdossier:
            to_reindex.append('is_subdossier')

    if context.portal_type in TYPES_WITH_CONTAINING_SUBDOSSIER_INDEX:
        to_reindex.append('containing_subdossier')

    context.reindexObject(idxs=to_reindex)

    # synchronize with model if necessary
    if ITask.providedBy(context):
        sync_task(context, event)
    def fix_child_mappings(self):
        dossier_brains = self.catalog(object_provides=IDossierMarker.__identifier__)
        for brain in dossier_brains:
            obj = brain.getObject()

            if ITemplateDossier.providedBy(obj):
                continue
            if obj.id in self.ignored_ids:
                continue

            self._fix_wrong_mappings(obj)

        for obj in self.objs_to_reindex:
            obj.reindexObject(idxs=['reference'])
            if ITask.providedBy(obj):
                obj.get_sql_object().sync_with(obj)
Example #49
0
    def get_parent_dossier(self):
        """Return the document's parent dossier.

        A parent dossier is available for documents in a dossier/subdossier
        or for documents in a task.

        No parent dossier is available for documents in an inbox, in a
        forwarding or inside a proposal. In that case this method returns None.

        """
        parent = aq_parent(aq_inner(self))
        if IDossierMarker.providedBy(parent) or IDossierTemplateMarker.providedBy(parent):
            return parent
        if ITask.providedBy(parent):
            return parent.get_containing_dossier()

        return None
Example #50
0
def create_subtask_response(context, event):
    """When adding a new task object within a task(subtask),
    it adds a response to the maintask.
    """

    # the event is fired multiple times when the task was transported, so we
    # need to verify that the request was not called by another client.
    request = context.REQUEST
    if request.get_header('X-OGDS-AC', None) or \
            request.get_header('X-OGDS-CID', None) or \
            request.get('X-CREATING-SUCCESSOR', None):
        return

    parent = aq_parent(aq_inner(context))

    if ITask.providedBy(parent):
        # add a response with a link to the object
        add_simple_response(parent, added_object=context)
Example #51
0
    def test_create_a_task_for_every_selected_person_with_multiple_orgunits(self, browser):
        client2 = create(Builder('org_unit')
                         .with_default_groups()
                         .id('client2')
                         .having(title='Client2',
                                 admin_unit=self.admin_unit))
        user = create(Builder('ogds_user')
                      .assign_to_org_units([client2])
                      .having(userid='some.user'))

        dossier = create(Builder('dossier'))
        doc = create(Builder("document").titled("test-doc")
                                        .within(dossier))

        responsible_users = [
            self.get_org_unit().id() + ':' + TEST_USER_ID,
            client2.id() + ':' + user.userid
        ]

        browser.login().visit(dossier)
        factoriesmenu.add('Task')
        browser.fill({'Title': 'Task title',
                      'Task Type': 'To comment',
                      'Related Items': doc})

        form = browser.find_form_by_field('Responsible')
        form.find_widget('Responsible').fill(responsible_users)

        browser.find('Save').click()

        tasks = filter(lambda item: ITask.providedBy(item),
                       dossier.objectValues())
        self.assertEquals(2, len(tasks), 'Expect 2 tasks')
        self.assertEquals(TEST_USER_ID, tasks[0].responsible)
        self.assertEquals('client1', tasks[0].responsible_client)
        self.assertEquals(user.userid, tasks[1].responsible)
        self.assertEquals('client2', tasks[1].responsible_client)

        activities = Activity.query.all()
        self.assertEquals(2, len(activities))
        self.assertEquals(u'task-added', activities[0].kind)
        self.assertEquals(TEST_USER_ID, activities[0].actor_id)
        self.assertEquals(u'task-added', activities[1].kind)
        self.assertEquals(TEST_USER_ID, activities[1].actor_id)
Example #52
0
    def get_task_info(self, item):
        """ return some task attributes for objects:
            Responsible client ID /  responsible
        """
        if not ITask.providedBy(item):
            return ""

        info = getUtility(IContactInformation)

        if not item.responsible_client or len(info.get_clients()) <= 1:
            # No responsible client is set yet or we have a single client
            # setup.
            return info.describe(item.responsible)

        # Client
        client = client_title_helper(item, item.responsible_client)

        taskinfo = "%s / %s" % (client, info.render_link(item.responsible))

        return taskinfo.encode("utf-8")
    def set_workflow_state(self, new_workflow_state_id, *objects):
        """Set the workflow state of one or many objects.
        When the state is changed for multiple nested objects at once, the
        method can optimize reindexing security so that it is not executed
        multiple times for the same object.
        """
        wftool = api.portal.get_tool('portal_workflow')

        for obj in objects:
            chain = wftool.getChainFor(obj)
            self.assertEquals(
                1, len(chain),
                'set_workflow_state does only support objects with'
                ' exactly one workflow, but {!r} has {!r}.'.format(obj, chain))
            workflow = wftool[chain[0]]
            self.assertIn(new_workflow_state_id, workflow.states)

            wftool.setStatusOf(chain[0], obj, {
                'review_state': new_workflow_state_id,
                'action': '',
                'actor': ''})
            workflow.updateRoleMappingsFor(obj)
            obj.reindexObject(idxs=['review_state'])

            if ITask.providedBy(obj):
                obj.get_sql_object().review_state = new_workflow_state_id

        # reindexObjectSecurity is recursive. We should avoid updating the same
        # object twice when the parent is changed too.
        security_reindexed = []
        for obj in sorted(objects, key=methodcaller('getPhysicalPath')):
            current_path = '/'.join(obj.getPhysicalPath())
            if any(filter(lambda path: current_path.startswith(path),
                          security_reindexed)):
                # We just have updated the security of a parent recursively,
                # thus the security of ``obj`` must be up to date at this point.
                break

            obj.reindexObjectSecurity()
            security_reindexed.append(current_path)
Example #54
0
    def _set_immediate_view(self, created):
        """The default behavior implemented by the dexterity add form is
        circumvented by this form. If there's only one task the immediate_view
        of the task fti is respected. If there is more than one task, a
        differen TaskRedirector implementation is used."""

        if len(created) == 1:
            task = created[0]
            fti = getUtility(IDexterityFTI, name=self.portal_type)
            if fti.immediate_view:
                self.immediate_view = "{0}/{1}/{2}".format(
                    self.context.absolute_url(),
                    task.id, fti.immediate_view,)
            else:
                self.immediate_view = "{0}/{1}".format(
                    self.context.absolute_url(),
                    task.id)
        else:
            if ITask.providedBy(self.context):
                redirect_to = '{0}#overview'.format(self.context.absolute_url())
            else:
                redirect_to = '{0}#tasks'.format(self.context.absolute_url())

            self.immediate_view = redirect_to
Example #55
0
def is_subtask(obj):
    """ is_subtask indexer
    """
    parent = aq_parent(aq_inner(obj))
    return ITask.providedBy(parent)
Example #56
0
 def is_inside_a_task(self):
     parent = aq_parent(aq_inner(self))
     return ITask.providedBy(parent)
 def progress_to_cancelled_guard(self, c, include_agency):
     """Checks if:
     The task is generated from tasktemplate and its the main task.
     """
     return self.context.is_from_tasktemplate and not \
         ITask.providedBy(aq_parent(self.context))
Example #58
0
def accept_forwarding_with_successor(
    context, predecessor_oguid, response_text, dossier=None):

    # the predessecor (the forwarding on the remote client)
    predecessor = getUtility(ITaskQuery).get_task_by_oguid(predecessor_oguid)

    # get the inbox
    cat = getToolByName(context, 'portal_catalog')
    inboxes = cat(portal_type="opengever.inbox.inbox")

    if len(inboxes) == 0:
        raise Unauthorized()
    else:
        inbox = inboxes[0].getObject()

    # transport the remote forwarding to the inbox or actual yearfolder
    transporter = getUtility(ITransporter)
    if dossier:
        yearfolder = _get_yearfolder(inbox, )
        successor_forwarding = transporter.transport_from(
            yearfolder, predecessor.client_id, predecessor.physical_path)
    else:
        successor_forwarding = transporter.transport_from(
            inbox, predecessor.client_id, predecessor.physical_path)

    # Replace the issuer with the current inbox
    successor_forwarding.issuer = u'inbox:%s' % get_client_id()

    # Set the "X-CREATING-SUCCESSOR" flag for preventing the event handler
    # from creating additional responses per added document.
    successor_forwarding.REQUEST.set('X-CREATING-SUCCESSOR', True)

    successor_tc = ISuccessorTaskController(successor_forwarding)

    # copy documents and map the intids
    doc_transporter = getUtility(ITaskDocumentsTransporter)
    with CustomInitialVersionMessage(
        _(u'version_message_accept_forwarding',
          default=u'Document copied from forwarding (forwarding accepted)'),
        context.REQUEST):
        intids_mapping = doc_transporter.copy_documents_from_remote_task(
            predecessor, successor_forwarding)

    # copy the responses
    response_transporter = IResponseTransporter(successor_forwarding)
    response_transporter.get_responses(predecessor.client_id,
                                       predecessor.physical_path,
                                       intids_mapping=intids_mapping)

    # if a dossier is given means that a successor task must
    # be created in a new or a existing dossier
    if dossier:
        # we need all task field values from the forwarding
        fielddata = {}
        for fieldname in ITask.names():
            value = ITask.get(fieldname).get(successor_forwarding)
            fielddata[fieldname] = value

        # lets create a new task - the successor task
        task = createContentInContainer(
            dossier, 'opengever.task.task', **fielddata)

        # copy documents and map the intids

        intids_mapping = _copy_documents_from_forwarding(
            successor_forwarding, task)

        # copy the responses
        response_transporter = IResponseTransporter(task)
        response_transporter.get_responses(
            get_client_id(),
            '/'.join(successor_forwarding.getPhysicalPath()),
            intids_mapping=intids_mapping)

        # successor
        successor_tc_task = ISuccessorTaskController(task)

    transaction.savepoint()

    # Close the predessecor forwarding
    response_text = response_text or ''
    request_data = {'response_text': response_text.encode('utf-8'),
                    'successor_oguid': successor_tc.get_oguid(),
                    'transition': 'forwarding-transition-accept'}

    response = remote_request(predecessor.client_id,
                              '@@store_forwarding_in_yearfolder',
                              path=predecessor.physical_path,
                              data=request_data)

    if response.read().strip() != 'OK':
        raise Exception('Adding the response and changing the '
                        'workflow state on the predecessor forwarding '
                        'failed.')

    if dossier:
        # when a successor task exists, we close also the successor forwarding
        change_task_workflow_state(
            successor_forwarding,
            'forwarding-transition-accept',
            text=response_text,
            successor_oguid=successor_tc_task.get_oguid())

    # create the succssor relations
    successor_tc.set_predecessor(predecessor_oguid)
    if dossier:
        successor_tc_task.set_predecessor(successor_tc.get_oguid())
        return task
    return successor_forwarding