def create_subtask(task, data): subtask = createContent('opengever.task.task', id=data['title'], **data) notify(ObjectCreatedEvent(subtask)) subtask = addContentToContainer(task, subtask, checkConstraints=True) for schemata in iterSchemata(subtask): super_repr = schemata(task) repr = schemata(subtask) for name, field in schema.getFieldsInOrder(schemata): if name in data: value = data[name] else: value = getattr(super_repr, name, None) setattr(repr, name, value) activity = TaskAddedActivity(subtask, task.REQUEST, task) activity.record() notify(ObjectModifiedEvent(subtask)) return subtask
def create_subtask(self, main_task, template, values): data = dict( title=template.title, issuer=template.issuer, responsible=template.responsible, responsible_client=template.responsible_client, task_type=template.task_type, text=template.text, relatedItems=self.related_documents, deadline=date.today() + timedelta(template.deadline), ) data.update(values) self.replace_interactive_actors(data) task = self.add_task(main_task, data) self.set_initial_state(task, template) task.reindexObject() task.get_sql_object().sync_with(task) # add activity record for subtask if api.content.get_state(task) != TASK_STATE_PLANNED: activity = TaskAddedActivity(task, getRequest(), main_task) activity.record() return task
def test_notification_mails_dont_interfere_with_txn_savepoints(self): # Login with a different user than task_responsible to trigger mail self.login(self.dossier_responsible) # Trigger a notification that dispatches a mail activity = TaskAddedActivity(self.task, getRequest(), self.dossier) activity.record() # Creating a savepoint will fail with the MailDataManager if it's # already registered as a transaction manager at that point transaction.savepoint()
def test_list_all_notifications_for_the_given_userid(self, browser): self.login(self.administrator, browser=browser) center = notification_center() self.assertEqual(0, Notification.query.count()) with freeze(datetime(2017, 10, 16, 0, 0, tzinfo=pytz.utc)): TaskAddedActivity(self.task, self.request, self.task.__parent__).record() for notification in Notification.query.all(): notification.is_read = True with freeze(datetime(2018, 10, 16, 0, 0, tzinfo=pytz.utc)): TaskAddedActivity(self.task, self.request, self.task.__parent__).record() self.assertEqual(2, len(center.get_watchers(self.task))) # two notifications for each watcher, the responsible and the issuer self.assertEqual(4, Notification.query.count()) self.login(self.regular_user, browser=browser) url = '{}/@notifications/{}'.format(self.portal.absolute_url(), self.regular_user.getId()) browser.open(url, method='GET', headers={'Accept': 'application/json'}) self.assertEqual(200, browser.status_code) self.assertEquals( [{u'@id': u'http://nohost/plone/@notifications/kathi.barfuss/3', u'actor_id': u'nicole.kohler', u'actor_label': u'Kohler Nicole', u'created': u'2018-10-16T00:00:00+00:00', u'label': u'Task opened', u'link': u'http://nohost/plone/@@resolve_notification?notification_id=3', u'notification_id': 3, u'read': False, u'summary': u'New task opened by Ziegler Robert', u'title': u'Vertragsentwurf \xdcberpr\xfcfen'}, {u'@id': u'http://nohost/plone/@notifications/kathi.barfuss/1', u'actor_id': u'nicole.kohler', u'actor_label': u'Kohler Nicole', u'created': u'2017-10-16T00:00:00+00:00', u'label': u'Task opened', u'link': u'http://nohost/plone/@@resolve_notification?notification_id=1', u'notification_id': 1, u'read': True, u'summary': u'New task opened by Ziegler Robert', u'title': u'Vertragsentwurf \xdcberpr\xfcfen'}], browser.json.get('items'))
def _create_task(self, task_payload): view = self.context.restrictedTraverse('++add++opengever.task.task') task_form = view.form_instance task_form.instance_schema = ITask task_form.updateFieldsFromSchemata() task_form.updateWidgets() task = task_form.create(task_payload) notify(ObjectCreatedEvent(task)) task_form.add(task) activity = TaskAddedActivity(task, self.request, self.context) activity.record() return task
def test_batch_notifications(self, browser): self.login(self.administrator, browser=browser) center = notification_center() self.assertEqual(0, Notification.query.count()) with freeze(datetime(2017, 10, 16, 0, 0, tzinfo=pytz.utc)): for i in range(5): TaskAddedActivity(self.task, self.request, self.task.__parent__).record() self.login(self.regular_user, browser=browser) batch_size = 2 url = '{}/@notifications/{}?b_size={}'.format( self.portal.absolute_url(), self.regular_user.getId(), batch_size) browser.open(url, method='GET', headers={'Accept': 'application/json'}) self.assertEqual(200, browser.status_code) self.assertEquals(5, browser.json.get('items_total')) self.assertEquals(2, len(browser.json.get('items'))) url = browser.json.get('batching').get('last') browser.open(url, method='GET', headers={'Accept': 'application/json'}) # 5 notifications with a batchsize of 2 will display only 1 notification # on the last batch self.assertEquals(1, len(browser.json.get('items')))
def open_next_task(self): next_task = self.get_sql_object().get_next_task() if not next_task: return next_task = next_task.oguid.resolve_object() if api.content.get_state(obj=next_task) == TASK_STATE_PLANNED: with as_internal_workflow_transition(): api.content.transition( obj=next_task, transition='task-transition-planned-open') next_task.sync() activity = TaskAddedActivity( next_task, getRequest(), aq_parent(next_task)) activity.record()
def test_returns_serialized_notifications_for_the_given_userid_and_notification_id(self, browser): self.login(self.dossier_responsible, browser=browser) self.assertEqual(0, Notification.query.count()) with freeze(datetime(2017, 10, 16, 0, 0, tzinfo=pytz.utc)): TaskAddedActivity(self.task, self.request, self.task.__parent__).record() url = '{}/@notifications/{}/1'.format(self.portal.absolute_url(), self.regular_user.getId()) self.login(self.regular_user, browser=browser) browser.open(url, method='GET', headers={'Accept': 'application/json'}) self.assertEqual(200, browser.status_code) self.assertEquals( {u'@id': u'http://nohost/plone/@notifications/kathi.barfuss/1', u'actor_id': u'robert.ziegler', u'actor_label': u'Ziegler Robert', u'created': u'2017-10-16T00:00:00+00:00', u'label': u'Task opened', u'link': u'http://nohost/plone/@@resolve_notification?notification_id=1', u'notification_id': 1, u'read': False, u'summary': u'New task opened by Ziegler Robert', u'title': u'Vertragsentwurf \xdcberpr\xfcfen'}, browser.json)
def open_next_task(self): next_task = self.get_sql_object().get_next_task() if not next_task: return next_task = next_task.oguid.resolve_object() if api.content.get_state(obj=next_task) == TASK_STATE_PLANNED: with as_internal_workflow_transition(): api.content.transition( obj=next_task, transition='task-transition-planned-open') next_task.sync() activity = TaskAddedActivity(next_task, getRequest(), aq_parent(next_task)) activity.record()
def after_transition_hook(self, transition, disable_sync, transition_params): response = add_simple_response(self.context, transition=transition, text=transition_params.get('text'), supress_activity=True) TaskAddedActivity( self.context, getRequest(), aq_parent(self.context)).record() self.save_related_items(response, transition_params.get('relatedItems')) self.sync_change(transition, transition_params.get('text'), disable_sync)
def create_subtask(self, main_task, template, related_documents): data = dict( title=template.title, issuer=self.replace_interactive_user(template.issuer), responsible=self.replace_interactive_user(template.responsible), task_type=template.task_type, text=template.text, relatedItems=related_documents, deadline=date.today() + timedelta(template.deadline), ) data['responsible_client'] = self.get_responsible_client( template, data['responsible']) task = createContent('opengever.task.task', **data) notify(ObjectCreatedEvent(task)) task = addContentToContainer(main_task, task, checkConstraints=True) self.mark_as_generated_from_tasktemplate(task) task.reindexObject() # add activity record for subtask activity = TaskAddedActivity(task, self.request, self.context) activity.record()
def test_raises_unauthorized_when_accessing_notification_of_other_user(self, browser): self.login(self.dossier_responsible, browser=browser) with freeze(datetime(2017, 10, 16, 0, 0, tzinfo=pytz.utc)): TaskAddedActivity(self.task, self.request, self.task.__parent__).record() # Different username in path with browser.expect_http_error(401): url = '{}/@notifications/{}/1'.format( self.portal.absolute_url(), self.regular_user.getId()) browser.open(url, data=json.dumps({}), method='PATCH', headers={'Accept': 'application/json'}) # Own username but foreign notification-id with browser.expect_http_error(401): url = '{}/@notifications/{}/1'.format( self.portal.absolute_url(), self.dossier_responsible.getId()) browser.open(url, data=json.dumps({}), method='PATCH', headers={'Accept': 'application/json'})
def test_mark_notification_as_read(self, browser): self.login(self.dossier_responsible, browser=browser) TaskAddedActivity(self.task, self.request, self.task.__parent__).record() url = '{}/@notifications/{}/{}'.format(self.portal.absolute_url(), self.regular_user.getId(), 1) self.login(self.regular_user, browser=browser) browser.open(url, method='GET', headers={'Accept': 'application/json'}) self.assertFalse(Notification.query.first().is_read) data = json.dumps({'read': True}) browser.open(url, data=data, method='PATCH', headers={'Accept': 'application/json'}) self.assertEqual(204, browser.status_code) self.assertTrue(Notification.query.first().is_read)
def record_added_activity(task, event): """Record task added activity, which also sets wathcers and create notifications. """ # Skip tasks created during successor creation, those are handled manually if getRequest().get('X-CREATING-SUCCESSOR', None): return # Skip tasks created during tasktemplatefolder triggering, those are # handled manually if IDuringTaskTemplateFolderTriggering.providedBy(getRequest()): return parent = aq_parent(aq_inner(task)) if IForwarding.providedBy(task): activity = ForwardingAddedActivity(task, getRequest(), parent) else: activity = TaskAddedActivity(task, getRequest(), parent) activity.record()
def create(self, paths=[]): """generate the task templates""" if 'abort' in self.request.keys(): return self.request.RESPONSE.redirect(self.context.absolute_url()) templates = [] for path in paths: templates.append(self.context.restrictedTraverse(path)) if len(templates) == 0: IStatusMessage(self.request).addStatusMessage(_( u'message_no_templates_selected', default=u'You have not selected any templates'), type="info") return self.request.RESPONSE.redirect(self.context.absolute_url()) # Create main task templatefolder = aq_parent(aq_inner(templates[0])) highest_deadline = max([temp.deadline for temp in templates]) deadline_timedelta = api.portal.get_registry_record( 'deadline_timedelta', interface=ITaskSettings) data = dict( title=templatefolder.title, issuer=self.replace_interactive_user('current_user'), responsible=self.replace_interactive_user('current_user'), responsible_client=get_current_org_unit().id(), task_type='direct-execution', deadline=date.today() + timedelta(highest_deadline + deadline_timedelta), ) main_task = createContent('opengever.task.task', **data) notify(ObjectCreatedEvent(main_task)) main_task = addContentToContainer(self.context, main_task, checkConstraints=True) ogdsservice = ogds_service() # set marker Interfaces alsoProvides(main_task, IFromTasktemplateGenerated) # set the main_task in to the in progress state wft = getToolByName(self.context, 'portal_workflow') wft.doActionFor(main_task, 'task-transition-open-in-progress') # create subtasks for template in templates: deadline = date.today() + timedelta(template.deadline) data = dict( title=template.title, issuer=self.replace_interactive_user(template.issuer), responsible=self.replace_interactive_user( template.responsible), task_type=template.task_type, text=template.text, deadline=deadline, ) if template.responsible_client == 'interactive_users': responsible_assigned_org_units = ogdsservice.assigned_org_units( data['responsible']) current_org_unit = get_current_org_unit() if not responsible_assigned_org_units or \ current_org_unit in responsible_assigned_org_units: data['responsible_client'] = current_org_unit.id() else: data['responsible_client'] = \ responsible_assigned_org_units[0].id() else: data['responsible_client'] = template.responsible_client task = createContent('opengever.task.task', **data) notify(ObjectCreatedEvent(task)) task = addContentToContainer(main_task, task, checkConstraints=True) alsoProvides(task, IFromTasktemplateGenerated) task.reindexObject() # add activity record for subtask activity = TaskAddedActivity(task, self.request, self.context) activity.record() # add activity record for the main task activity = TaskAddedActivity(main_task, self.request, self.context) activity.record() IStatusMessage(self.request).addStatusMessage(_( u'message_tasks_created', default=u'tasks created'), type="info") return self.request.RESPONSE.redirect('%s#tasks' % self.context.absolute_url())
def create(self, paths=[]): """generate the task templates""" if "abort" in self.request.keys(): return self.request.RESPONSE.redirect(self.context.absolute_url()) templates = [] for path in paths: templates.append(self.context.restrictedTraverse(path)) if len(templates) == 0: IStatusMessage(self.request).addStatusMessage( _(u"message_no_templates_selected", default=u"You have not selected any templates"), type="info" ) return self.request.RESPONSE.redirect(self.context.absolute_url()) # Create main task templatefolder = aq_parent(aq_inner(templates[0])) highest_deadline = max([temp.deadline for temp in templates]) data = dict( title=templatefolder.title, issuer=self.replace_interactive_user("current_user"), responsible=self.replace_interactive_user("current_user"), responsible_client=get_current_org_unit().id(), task_type="direct-execution", deadline=date.today() + timedelta(highest_deadline + MAIN_TASK_DEADLINE_DELTA), ) main_task = createContent("opengever.task.task", **data) notify(ObjectCreatedEvent(main_task)) main_task = addContentToContainer(self.context, main_task, checkConstraints=True) ogdsservice = ogds_service() # set marker Interfaces alsoProvides(main_task, IFromTasktemplateGenerated) # set the main_task in to the in progress state wft = getToolByName(self.context, "portal_workflow") wft.doActionFor(main_task, "task-transition-open-in-progress") # create subtasks for template in templates: deadline = date.today() + timedelta(template.deadline) data = dict( title=template.title, issuer=self.replace_interactive_user(template.issuer), responsible=self.replace_interactive_user(template.responsible), task_type=template.task_type, text=template.text, deadline=deadline, ) if template.responsible_client == "interactive_users": responsible_assigned_org_units = ogdsservice.assigned_org_units(data["responsible"]) current_org_unit = get_current_org_unit() if not responsible_assigned_org_units or current_org_unit in responsible_assigned_org_units: data["responsible_client"] = current_org_unit.id() else: data["responsible_client"] = responsible_assigned_org_units[0].id() else: data["responsible_client"] = template.responsible_client task = createContent("opengever.task.task", **data) notify(ObjectCreatedEvent(task)) task = addContentToContainer(main_task, task, checkConstraints=True) alsoProvides(task, IFromTasktemplateGenerated) task.reindexObject() # add activity record for subtask activity = TaskAddedActivity(task, self.request, self.context) activity.record() # add activity record for the main task activity = TaskAddedActivity(main_task, self.request, self.context) activity.record() IStatusMessage(self.request).addStatusMessage( _(u"message_tasks_created", default=u"tasks created"), type="info" ) return self.request.RESPONSE.redirect("%s#tasks" % self.context.absolute_url())