Exemplo n.º 1
0
    def change_remote_tasks_workflow_state(
        self, transition, text, responsible='', responsible_client=''):

        tasks = self.get_tasks_to_sync(transition)
        if not tasks:
            return False

        for task in tasks:

            response = utils.remote_request(
                task.client_id,
                '@@sync-task-workflow-state-receive',
                task.physical_path,
                data={'transition': transition,
                      'text': text and text.encode('utf-8') or '',
                      'responsible': responsible,
                      'responsible_client': responsible_client})

            response_data = response.read().strip()
            if response_data != 'OK':
                raise Exception(
                    'Could not change task on remote client %s (%s)' % (
                        task.client_id,
                        task.physical_path))

        return tasks
Exemplo n.º 2
0
def accept_task_with_successor(dossier, predecessor_oguid, response_text):

    predecessor = getUtility(ITaskQuery).get_task_by_oguid(predecessor_oguid)

    # Transport the original task (predecessor) to this dossier. The new
    # response and task change is not yet done and will be done later. This
    # is necessary for beeing as transaction aware as possible.
    transporter = getUtility(ITransporter)
    successor = transporter.transport_from(dossier, predecessor.client_id,
                                           predecessor.physical_path)
    successor_tc = ISuccessorTaskController(successor)

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

    # copy documents and map the intids
    doc_transporter = getUtility(ITaskDocumentsTransporter)
    with CustomInitialVersionMessage(
            _(u'version_message_accept_task',
              default=u'Document copied from task (task accepted)'),
            dossier.REQUEST):
        intids_mapping = doc_transporter.copy_documents_from_remote_task(
            predecessor, successor)

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

    # First "accept" the successor task..
    accept_task_with_response(successor, response_text)

    transaction.savepoint()
    response_text = response_text or ''
    request_data = {
        'text': response_text.encode('utf-8'),
        'successor_oguid': successor_tc.get_oguid()
    }

    response = remote_request(predecessor.client_id,
                              '@@accept_task_workflow_transition',
                              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 task '
                        'failed.')

    # Connect the predecessor and the successor task. This needs to be done
    # that late for preventing a deadlock because of the locked tasks table.
    successor_tc.set_predecessor(predecessor_oguid)

    return successor
Exemplo n.º 3
0
def set_remote_import_stamp(context):
    """update the sync stap on every enabled client."""

    timestamp = update_sync_stamp(context)

    # fake the request, because the remote_request expects it
    setRequest(context.REQUEST)

    info = getUtility(IContactInformation)
    for client in info.get_clients():
        try:
            remote_request(client.client_id, '@@update_sync_stamp',
                       data={REQUEST_SYNC_KEY: timestamp})
            logger.info(
                "Issued remote request to update sync_stamp on %s to %s" % (
                    client.client_id, timestamp))
        except URLError, e:
            logger.warn("ERROR while trying to remotely update sync_stamp"
                        "for %s: %s" % (client.client_id, e))
Exemplo n.º 4
0
def set_remote_import_stamp(context):
    """update the sync stap on every enabled client."""

    timestamp = update_sync_stamp(context)

    # fake the request, because the remote_request expects it
    setRequest(context.REQUEST)

    info = getUtility(IContactInformation)
    for client in info.get_clients():
        try:
            remote_request(client.client_id,
                           '@@update_sync_stamp',
                           data={REQUEST_SYNC_KEY: timestamp})
            logger.info(
                "Issued remote request to update sync_stamp on %s to %s" %
                (client.client_id, timestamp))
        except URLError, e:
            logger.warn("ERROR while trying to remotely update sync_stamp"
                        "for %s: %s" % (client.client_id, e))
Exemplo n.º 5
0
    def _update_remote_task(self, task, responsible, responsible_client):
        response = remote_request(
            task.client_id,
            '@@sync-task-workflow-state-receive',
            task.physical_path,
            data={'transition': u'task-transition-reassign',
                  'text': 'Neu zuweisen',
                  'responsible': responsible,
                  'responsible_client': responsible_client})

        return response
Exemplo n.º 6
0
def accept_task_with_successor(dossier, predecessor_oguid, response_text):

    predecessor = getUtility(ITaskQuery).get_task_by_oguid(predecessor_oguid)

    # Transport the original task (predecessor) to this dossier. The new
    # response and task change is not yet done and will be done later. This
    # is necessary for beeing as transaction aware as possible.
    transporter = getUtility(ITransporter)
    successor = transporter.transport_from(
        dossier, predecessor.client_id, predecessor.physical_path)
    successor_tc = ISuccessorTaskController(successor)

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

    # copy documents and map the intids
    doc_transporter = getUtility(ITaskDocumentsTransporter)
    with CustomInitialVersionMessage(
        _(u'version_message_accept_task',
          default=u'Document copied from task (task accepted)'),
        dossier.REQUEST):
        intids_mapping = doc_transporter.copy_documents_from_remote_task(
            predecessor, successor)

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

    # First "accept" the successor task..
    accept_task_with_response(successor, response_text)

    transaction.savepoint()
    response_text = response_text or ''
    request_data = {'text': response_text.encode('utf-8'),
                    'successor_oguid': successor_tc.get_oguid()}

    response = remote_request(predecessor.client_id,
                              '@@accept_task_workflow_transition',
                              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 task '
                        'failed.')

    # Connect the predecessor and the successor task. This needs to be done
    # that late for preventing a deadlock because of the locked tasks table.
    successor_tc.set_predecessor(predecessor_oguid)

    return successor
Exemplo n.º 7
0
    def push_to_remote_client(self, key, client_id):
        data = dict(self.get_data(key))
        del data['__created']

        req_data = {'data-set': json.dumps(data), 'key': key}
        response = remote_request(client_id,
                                  '@@receive-wizard-data-set',
                                  data=req_data)

        if response.read().strip() != 'OK':
            raise Exception('Could not push session data to client %s' %
                            (client_id))
Exemplo n.º 8
0
    def _update_remote_task(self, task, responsible, responsible_client):
        response = remote_request(task.client_id,
                                  '@@sync-task-workflow-state-receive',
                                  task.physical_path,
                                  data={
                                      'transition':
                                      u'task-transition-reassign',
                                      'text': 'Neu zuweisen',
                                      'responsible': responsible,
                                      'responsible_client': responsible_client
                                  })

        return response
Exemplo n.º 9
0
    def push_to_remote_client(self, key, client_id):
        data = dict(self.get_data(key))
        del data['__created']

        req_data = {'data-set': json.dumps(data),
                    'key': key}
        response = remote_request(client_id,
                                  '@@receive-wizard-data-set',
                                  data=req_data)

        if response.read().strip() != 'OK':
            raise Exception('Could not push session data to client %s' % (
                    client_id))
Exemplo n.º 10
0
    def sync_deadline(self, new_deadline, text):
        sct = ISuccessorTaskController(self.context)
        for successor in sct.get_successors():

            response = remote_request(
                successor.client_id,
                '@@remote_deadline_modifier',
                successor.physical_path,
                data={
                    'new_deadline': new_deadline.toordinal(),
                    'text': text})

            if response.read().strip() != 'OK':
                raise Exception(
                    'Updating deadline on remote client %s. failed (%s)' % (
                        successor.client_id, response.read()))
Exemplo n.º 11
0
    def sync_deadline(self, new_deadline, text):
        sct = ISuccessorTaskController(self.context)
        for successor in sct.get_successors():

            response = remote_request(
                successor.client_id,
                '@@remote_deadline_modifier',
                successor.physical_path,
                data={
                    'new_deadline': new_deadline.toordinal(),
                    'text': text})

            if response.read().strip() != 'OK':
                raise Exception(
                    'Updating deadline on remote client %s. failed (%s)' % (
                        successor.client_id, response.read()))
Exemplo n.º 12
0
    def send_responses(self, target_cid, remote_task_url, intids_mapping=None):
        """ Sends all responses of task self.context to task on
        a remote client.
        `target_cid`: client_id of a target client
        `remote_task_url`: url to a task on `target_cid` relative
        to its site root.
        `intids_mapping`: replace intids of RelationValues according
        to this mapping. This fixes the intids on remote clients.
        RelationValues not listed in this mapping will not be sent.
        """

        jsondata = self.extract_responses(intids_mapping)

        return remote_request(target_cid,
                              '@@task-responses-receive',
                              path=remote_task_url,
                              data=dict(responses=jsondata))
Exemplo n.º 13
0
    def send_responses(self, target_cid, remote_task_url,
                       intids_mapping=None):
        """ Sends all responses of task self.context to task on
        a remote client.
        `target_cid`: client_id of a target client
        `remote_task_url`: url to a task on `target_cid` relative
        to its site root.
        `intids_mapping`: replace intids of RelationValues according
        to this mapping. This fixes the intids on remote clients.
        RelationValues not listed in this mapping will not be sent.
        """

        jsondata = self.extract_responses(intids_mapping)

        return remote_request(target_cid,
                                   '@@task-responses-receive',
                                   path=remote_task_url,
                                   data=dict(responses=jsondata))
Exemplo n.º 14
0
    def get_responses(self, target_cid, remote_task_path, intids_mapping):
        """Retrieves all responses from the task with path `remote_task_path`
        on the client `client` and adds them to the current context (target
        task).

        Provide a an `intids_mapping` (dict), mapping the original intids of
        related objects to the new intids of the copies on this client. This
        is necessary for fixing the relations.
        """

        req_data = {'intids_mapping': json.dumps(intids_mapping)}
        response = remote_request(target_cid,
                                  '@@task-responses-extract',
                                  path=remote_task_path,
                                  data=req_data)
        try:
            data = json.loads(response.read())
        except ValueError:
            #is a internal request
            data = response.read()

        self.create_responses(data)
Exemplo n.º 15
0
    def get_responses(self, target_cid, remote_task_path, intids_mapping):
        """Retrieves all responses from the task with path `remote_task_path`
        on the client `client` and adds them to the current context (target
        task).

        Provide a an `intids_mapping` (dict), mapping the original intids of
        related objects to the new intids of the copies on this client. This
        is necessary for fixing the relations.
        """

        req_data = {'intids_mapping': json.dumps(intids_mapping)}
        response = remote_request(target_cid,
                                  '@@task-responses-extract',
                                  path=remote_task_path,
                                  data=req_data)
        try:
            data = json.loads(response.read())
        except ValueError:
            #is a internal request
            data = response.read()

        self.create_responses(data)
Exemplo n.º 16
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
Exemplo n.º 17
0
    def deliver_documents_and_complete_task(self, formdata, response):
        """Delivers the selected documents to the predecesser task and
        complete the task:

        - Copy the documents to the predecessor task (no new responses)
        - Execute workflow transition (no new response)
        - Add a new response indicating the workflow transition, the added
        documents and containing the entered response text.
        """

        # add documents to the response
        response.added_object = PersistentList()

        predecessor = getUtility(ITaskQuery).get_task_by_oguid(
            self.context.predecessor)

        transporter = getUtility(ITransporter)
        intids = getUtility(IIntIds)

        data = {
            'documents': [],
            'text': formdata['text'],
            'transition': formdata['transition']
        }

        related_ids = []
        if getattr(self.context, 'relatedItems'):
            related_ids = [item.to_id for item in self.context.relatedItems]

        for doc_intid in formdata['documents']:
            doc = intids.getObject(int(doc_intid))
            data['documents'].append(transporter._extract_data(doc))

            # add a releation when a document from the dossier was selected
            if int(doc_intid) not in related_ids:
                # check if its a relation
                if aq_parent(aq_inner(doc)) != self.context:
                    # add relation to doc on task
                    if self.context.relatedItems:
                        self.context.relatedItems.append(
                            RelationValue(int(doc_intid)))
                    else:
                        self.context.relatedItems = [
                            RelationValue(int(doc_intid))
                        ]

                    # add response change entry for this relation
                    if not response.relatedItems:
                        response.relatedItems = [RelationValue(int(doc_intid))]
                    else:
                        response.relatedItems.append(
                            RelationValue(int(doc_intid)))

                    # set relation flag
                    doc._v__is_relation = True
                    response.add_change(
                        'relatedItems',
                        _(u'label_related_items', default=u"Related Items"),
                        '', linked(doc, doc.Title()))

                else:
                    # add entry to the response for this document
                    response.added_object.append(RelationValue(int(doc_intid)))
            else:
                # append only the relation on the response
                doc._v__is_relation = True
                response.add_change(
                    'relatedItems',
                    _(u'label_related_items', default=u"Related Items"), '',
                    linked(doc, doc.Title()))

        request_data = {'data': json.dumps(data)}
        response = remote_request(predecessor.client_id,
                                  '@@complete_successor_task-receive_delivery',
                                  predecessor.physical_path,
                                  data=request_data)

        if response.read().strip() != 'OK':
            raise Exception('Delivering documents and updating task failed '
                            'on remote client %s.' % predecessor.client_id)
Exemplo n.º 18
0
    def deliver_documents_and_complete_task(self, formdata, response):
        """Delivers the selected documents to the predecesser task and
        complete the task:

        - Copy the documents to the predecessor task (no new responses)
        - Execute workflow transition (no new response)
        - Add a new response indicating the workflow transition, the added
        documents and containing the entered response text.
        """

        # add documents to the response
        response.added_object = PersistentList()

        predecessor = getUtility(ITaskQuery).get_task_by_oguid(self.context.predecessor)

        transporter = getUtility(ITransporter)
        intids = getUtility(IIntIds)

        data = {"documents": [], "text": formdata["text"], "transition": formdata["transition"]}

        related_ids = []
        if getattr(self.context, "relatedItems"):
            related_ids = [item.to_id for item in self.context.relatedItems]

        for doc_intid in formdata["documents"]:
            doc = intids.getObject(int(doc_intid))
            data["documents"].append(transporter._extract_data(doc))

            # add a releation when a document from the dossier was selected
            if int(doc_intid) not in related_ids:
                # check if its a relation
                if aq_parent(aq_inner(doc)) != self.context:
                    # add relation to doc on task
                    if self.context.relatedItems:
                        self.context.relatedItems.append(RelationValue(int(doc_intid)))
                    else:
                        self.context.relatedItems = [RelationValue(int(doc_intid))]

                    # add response change entry for this relation
                    if not response.relatedItems:
                        response.relatedItems = [RelationValue(int(doc_intid))]
                    else:
                        response.relatedItems.append(RelationValue(int(doc_intid)))

                    # set relation flag
                    doc._v__is_relation = True
                    response.add_change(
                        "relatedItems",
                        _(u"label_related_items", default=u"Related Items"),
                        "",
                        linked(doc, doc.Title()),
                    )

                else:
                    # add entry to the response for this document
                    response.added_object.append(RelationValue(int(doc_intid)))
            else:
                # append only the relation on the response
                doc._v__is_relation = True
                response.add_change(
                    "relatedItems", _(u"label_related_items", default=u"Related Items"), "", linked(doc, doc.Title())
                )

        request_data = {"data": json.dumps(data)}
        response = remote_request(
            predecessor.client_id,
            "@@complete_successor_task-receive_delivery",
            predecessor.physical_path,
            data=request_data,
        )

        if response.read().strip() != "OK":
            raise Exception(
                "Delivering documents and updating task failed " "on remote client %s." % predecessor.client_id
            )
Exemplo n.º 19
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