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
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
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))
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))
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
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
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))
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
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))
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()))
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))
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)
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
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)
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 )
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