def test_set_predecessor_with_valid_oguid_returns_true(self): task1 = create(Builder('task')) task2 = create(Builder('task')) task2_oguid = ISuccessorTaskController(task2).get_oguid() self.assertTrue( ISuccessorTaskController(task1).set_predecessor(task2_oguid))
def handle_continue(self, action): data, errors = self.extractData() if not errors: oguid = ISuccessorTaskController(self.context).get_oguid() # set forwarding flag is_forwarding = True dm = getUtility(IWizardDataStorage) dmkey = 'accept:%s' % oguid dm.set(dmkey, u'is_forwarding', is_forwarding) # activate the assign to dossier mode dm.set(dmkey, u'is_only_assign', True) dm.update(dmkey, data) method = data.get('method') if method == 'existing_dossier': url = '{}/@@accept_choose_dossier?oguid={}'.format( self.context.get_responsible_org_unit().admin_unit. public_url, oguid) return self.request.RESPONSE.redirect(url) elif method == 'new_dossier': oguid = ISuccessorTaskController(self.context).get_oguid() url = '{}/@@accept_select_repositoryfolder?oguid={}'.format( self.context.get_responsible_org_unit().admin_unit. public_url, oguid) return self.request.RESPONSE.redirect(url)
def test_set_predecessor_with_invalid_oguid_returns_false(self): task1 = create(Builder('task')) self.assertFalse( ISuccessorTaskController(task1).set_predecessor(u'incorrect:2')) self.assertFalse( ISuccessorTaskController(task1).set_predecessor(u'client1:3'))
def test_oguid_is_admin_unit_id_and_task_id_separated_by_a_colon(self): intids = getUtility(IIntIds) task1 = create(Builder('task')) task2 = create(Builder('task')) self.assertEquals(u'client1:%s' % (intids.getId(task1)), ISuccessorTaskController(task1).get_oguid()) self.assertEquals(u'client1:%s' % (intids.getId(task2)), ISuccessorTaskController(task2).get_oguid())
def test_successor_is_also_updated_when_modify_predecessors_deadline( self, browser): self.login(self.dossier_responsible, browser=browser) # Make predecessor <-> successor pair predecessor = self.task successor = self.seq_subtask_1 ISuccessorTaskController(successor).set_predecessor( ISuccessorTaskController(predecessor).get_oguid()) self._change_deadline(predecessor, datetime.date(2013, 10, 1), 'Lorem Ipsum') self.assertEquals(successor.deadline, datetime.date(2013, 10, 1))
def test_oguid_by_path_returns_none_for_invalid_path(self): task = create(Builder('task')) controller = ISuccessorTaskController(task) self.assertEquals( None, controller.get_oguid_by_path('/plone/not-existing/', 'client1'))
def test_successor_is_also_updated_when_modify_predecessors_deadline( self, browser): predecessor = create( Builder('task').having(issuer=TEST_USER_ID, deadline=datetime.date(2013, 1, 1))) succesor = create( Builder('task').having(issuer=TEST_USER_ID, deadline=datetime.date(2013, 1, 1))) ISuccessorTaskController(succesor).set_predecessor( ISuccessorTaskController(predecessor).get_oguid()) self._change_deadline(predecessor, datetime.date(2013, 10, 1), 'Lorem Ipsum') self.assertEquals(succesor.deadline, datetime.date(2013, 10, 1))
def test_response_view(self): # test added objects info add_simple_response(self.task, text=u'field', added_object=[self.doc1, self.doc2]) # test field changes info add_simple_response(self.task, text=u'field', field_changes=( (ITask['responsible'], TEST_USER_ID), (ITask['responsible_client'], 'plone'), ), transition=u'task-transition-open-in-progress') # test successsor info successor_oguid = ISuccessorTaskController(self.successor).get_oguid() add_simple_response(self.task, successor_oguid=successor_oguid) transaction.commit() self.assertEquals(len(IResponseContainer(self.task)), 3) # test different responeses and their infos self.browser.open('%s/tabbedview_view-overview' % self.task.absolute_url()) # TODO: replace with OGBrowse API. What is it looking for? self.assertEquals( 'Added successor task', self.browser.css('div.response-info div span.label') [0].plain_text()) successor_info = """<span class="issueChange"><span class="wf-task-state-open"><a href="http://nohost/plone/dossier-1/task-2" title="[Plone] > dossier-1 > Test task 1"><span class="rollover-breadcrumb icon-task-remote-task">Test task 1</span></a> <span class="discreet">(Client2 / <a href="http://nohost/plone/@@user-details/testuser2">User 2 Test (testuser2)</a>)</span></span></span>""" self.assertTrue(successor_info in self.browser.contents) responsible_container = self.browser.xpath( "//div[@class='response-info']/div[descendant-or-self::*[contains(text(), 'label_responsible')]]" )[0] links = responsible_container.xpath("./*/a") self.assertEquals( ['User 2 Test (testuser2)', 'User Test (test_user_1_)'], [l.text for l in links]) self.assertEquals([ 'http://nohost/plone/@@user-details/testuser2', 'http://nohost/plone/@@user-details/test_user_1_' ], [l.attrib["href"] for l in links]) documents = self.browser.css( ".contenttype-opengever-document-document") self.assertEquals(['Doc 1', 'Doc 2'], [d.plain_text() for d in documents]) self.assertEquals([ 'http://nohost/plone/dossier-1/document-1', 'http://nohost/plone/dossier-1/document-2' ], [d.attrib["href"] for d in documents]) # edit and delete should not be possible self.assertEquals([], self.browser.css("input[type='submit']"))
def accept_task_with_successor(dossier, predecessor_oguid, response_text): predecessor = Task.query.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 = Transporter() successor = transporter.transport_from(dossier, predecessor.admin_unit_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) comment = _(u'version_message_accept_task', default=u'Document copied from task (task accepted)') intids_mapping = doc_transporter.copy_documents_from_remote_task( predecessor, successor, comment=comment) # copy the responses response_transporter = IResponseTransporter(successor) response_transporter.get_responses(predecessor.admin_unit_id, predecessor.physical_path, intids_mapping=intids_mapping) # Move current responsible from predecessor task to successor center = notification_center() center.add_task_responsible(successor, successor.responsible) # 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 = dispatch_request(predecessor.admin_unit_id, '@@accept_task_workflow_transition', path=predecessor.physical_path, data=request_data) response_body = response.read() if response_body.strip() != 'OK': raise TaskRemoteRequestError( '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 test_oguid_by_path_returns_none_for_invalid_admin_unit_id(self): task = create(Builder('task')) controller = ISuccessorTaskController(task) self.assertEquals( None, controller.get_oguid_by_path('/'.join(task.getPhysicalPath()), 'client2'))
def after_create(self, obj): wtool = getToolByName(obj, 'portal_workflow') for transition in self.transitions: wtool.doActionFor(obj, transition) if self.predecessor: ISuccessorTaskController(obj).set_predecessor(self.predecessor) super(TaskBuilder, self).after_create(obj)
def get_predecessor_task(self): """ Get the original task """ controller = ISuccessorTaskController(self.context) task = controller.get_predecessor() # box rendering need a list if not task: return [] return [task]
def get_related_tasks_to_sync(self, transition=''): tasks = [] stc = ISuccessorTaskController(self.context) predecessor = stc.get_predecessor(None) if predecessor: tasks.append(predecessor) tasks.extend(stc.get_successors()) return tasks
def test_oguid_by_path_returns_the_oguid_of_the_accordant_task(self): intids = getUtility(IIntIds) url_tool = getToolByName(self.portal, 'portal_url') task = create(Builder('task')) controller = ISuccessorTaskController(task) self.assertEquals( u'client1:%s' % (intids.getId(task)), controller.get_oguid_by_path( '/'.join(url_tool.getRelativeContentPath(task)), 'client1'))
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
def after_create(self, obj): wtool = getToolByName(obj, 'portal_workflow') for transition in self.transitions: wtool.doActionFor(obj, transition) if self.predecessor: ISuccessorTaskController(obj).set_predecessor(self.predecessor) if self._as_sequential_task: alsoProvides(obj, IFromSequentialTasktemplate) super(TaskBuilder, self).after_create(obj)
def after_transition_hook(self, transition, disable_sync, transition_params): successor_task = self.create_successor_task(transition_params['dossier']) add_simple_response( self.context, transition=transition, text=transition_params.get('text'), successor_oguid=Oguid.for_object(successor_task).id) # set predecessor on successor task successor_tc_task = ISuccessorTaskController(successor_task) successor_tc_task.set_predecessor(Oguid.for_object(self.context).id) IYearfolderStorer(self.context).store_in_yearfolder() return successor_task
def updateWidgets(self): if self.request.form.get('form.widgets.text', None) is None: if self.request.get('oguid', None) is None: oguid = ISuccessorTaskController(self.context).get_oguid() self.request.set('oguid', oguid) dm = getUtility(IWizardDataStorage) dmkey = 'accept:%s' % self.request.get('oguid') text = dm.get(dmkey, 'text') if text: self.request.set('form.widgets.text', text) super(ChooseMethodStepForm, self).updateWidgets()
def _is_close_successor_wizard_possible(self, transition): if not self._is_responsible_or_inbox_group_user(): return False elif not self.context.predecessor: return False # check if the predessecor is a forwarding # in this case the successor wizard isn't possible and necessary elif ISuccessorTaskController(self.context).get_predecessor( ).task_type == u'forwarding_task_type': return False else: return True
def test_successors_predecessor_relation(self): task1 = create(Builder('task')) task2 = create(Builder('task')) task3 = create(Builder('task')) task1_oguid = ISuccessorTaskController(task1).get_oguid() task1_sql = ISuccessorTaskController(task1).get_indexed_data() task2_sql = ISuccessorTaskController(task2).get_indexed_data() task3_sql = ISuccessorTaskController(task3).get_indexed_data() ISuccessorTaskController(task2).set_predecessor(task1_oguid) ISuccessorTaskController(task3).set_predecessor(task1_oguid) self.assertEquals(task1_sql, ISuccessorTaskController(task2).get_predecessor()) self.assertEquals(task1_sql, ISuccessorTaskController(task3).get_predecessor()) self.assertEquals([task2_sql, task3_sql], ISuccessorTaskController(task1).get_successors())
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 test_forwarding_predecessors_are_skipped_when_syncing_deadline_modification( self, browser): self.login(self.secretariat_user, browser=browser) # Make predecessor (forwarding) <-> successor (task) pair, like # it's created when assigning a forwarding to a dossier. predecessor = self.inbox_forwarding successor = self.seq_subtask_1 ISuccessorTaskController(successor).set_predecessor( Oguid.for_object(predecessor).id) self._change_deadline(successor, datetime.date(2013, 10, 1), 'Lorem Ipsum') self.assertEquals(successor.deadline, datetime.date(2013, 10, 1)) self.assertEquals(None, predecessor.deadline)
def get_tasks_to_sync(self, transition): if not self._is_synced_transition(transition): return [] tasks = [] stc = ISuccessorTaskController(self.context) predecessor = stc.get_predecessor(None) #Fowarding predecessors should not be synced. if (predecessor is not None and predecessor.task_type != u'forwarding_task_type'): tasks.append(predecessor) tasks.extend(stc.get_successors()) return tasks
def updateWidgets(self): if self.request.form.get('form.widgets.transition', None) is None: self.request.set('form.widgets.transition', self.request.get('transition')) # Use text passed from response-add-form. if self.request.form.get('form.widgets.text', None) is None: dm = getUtility(IWizardDataStorage) oguid = ISuccessorTaskController(self.context).get_oguid() dmkey = 'delegate:%s' % oguid text = dm.get(dmkey, 'text') if text: self.request.set('form.widgets.text', text) Form.updateWidgets(self) self.widgets['transition'].mode = HIDDEN_MODE
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
def updateWidgets(self): if self.request.form.get('form.widgets.text', None) is None: if self.request.get('oguid', None) is None: oguid = ISuccessorTaskController(self.context).get_oguid() self.request.set('oguid', oguid) dm = getUtility(IWizardDataStorage) dmkey = 'accept:%s' % self.request.get('oguid') text = dm.get(dmkey, 'text') if text: self.request.set('form.widgets.text', text) super(ChooseMethodStepForm, self).updateWidgets() if self.context.task_type == 'forwarding_task_type': self.widgets.get('method').label = _( u'label_accept_forwarding_choose_method', default="Accept forwarding and ...")
def test_set_predecessor_resets_issuing_org_unit_to_predecessors_one(self): extra_au = create(Builder('admin_unit').id(u'extra-au')) extra_ou = create( Builder('org_unit').having(admin_unit=extra_au).id(u'extra-ou')) create( Builder('globalindex_task').having(int_id='1234', issuing_org_unit='extra-ou', admin_unit_id='extra-au')) successor = create( Builder('task').having(responsible_client='org-unit-1')) self.assertEquals(self.org_unit, successor.get_sql_object().get_issuing_org_unit()) ISuccessorTaskController(successor).set_predecessor('extra-au:1234') self.assertEquals(extra_ou, successor.get_sql_object().get_issuing_org_unit())
def test_set_predecessor_resets_issuing_org_unit_to_predecessors_one(self): additional_admin_unit = create(Builder('admin_unit').id(u'additional')) additional = create( Builder('org_unit').having( admin_unit=additional_admin_unit).id(u'additional')) create( Builder('globalindex_task').having(int_id='1234', issuing_org_unit='additional', admin_unit_id='additional')) successor = create(Builder('task')) self.assertEquals(self.org_unit, successor.get_sql_object().get_issuing_org_unit()) ISuccessorTaskController(successor).set_predecessor('additional:1234') self.assertEquals(additional, successor.get_sql_object().get_issuing_org_unit())
def handle_continue(self, action): data, errors = self.extractData() if not errors: oguid = ISuccessorTaskController(self.context).get_oguid() dm = getUtility(IWizardDataStorage) dmkey = 'close:%s' % oguid dm.update(dmkey, data) if len(data['documents']) == 0: self.close_task(data.get('text')) return self.request.RESPONSE.redirect( self.context.absolute_url()) else: admin_unit = self.context.get_responsible_admin_unit() dm.push_to_remote_client(dmkey, admin_unit.id()) url = '/'.join( (admin_unit.public_url, '@@close-task-wizard_choose-dossier?oguid=%s' % (oguid))) return self.request.RESPONSE.redirect(url)
def handle_continue(self, action): data, errors = self.extractData() if not errors: oguid = ISuccessorTaskController(self.context).get_oguid() dm = getUtility(IWizardDataStorage) dmkey = 'close:%s' % oguid dm.update(dmkey, data) if len(data['documents']) == 0: url = '/'.join((self.context.absolute_url(), '@@close-task-wizard_close?oguid=%s' % oguid)) return self.request.RESPONSE.redirect(url) else: info = getUtility(IContactInformation) client = info.get_client_by_id(self.context.responsible_client) dm.push_to_remote_client(dmkey, client.client_id) url = '/'.join( (client.public_url, '@@close-task-wizard_choose-dossier?oguid=%s' % (oguid))) return self.request.RESPONSE.redirect(url)