def handle_cycle_task_status_change(*objs): """Notification handling for task's status change.""" declined_status = all_models.CycleTaskGroupObjectTask.DECLINED declined_tasks = {obj for obj in objs if obj.status == declined_status} pusher.create_notifications_for_objects( pusher.get_notification_type("cycle_task_declined"), datetime.date.today(), *(declined_tasks))
def handle_cycle_created(obj, manually): today = datetime.date.today() if manually: create_notification = "manual_cycle_created" else: create_notification = "cycle_created" pusher.update_or_create_notifications(obj, today, create_notification) if not obj.is_current: return notification_names = [ get_notif_name_by_wf(obj.workflow), create_notification, "cycle_task_overdue", "cycle_task_due_today" ] tasks = list(obj.cycle_task_group_object_tasks) query = pusher.get_notification_query( *tasks, **{"notification_names": notification_names}) exists_notifications = collections.defaultdict(set) for notification in query: exists_notifications[notification.notification_type_id].add( notification.object_id) for notification_type in pusher.get_notification_types( *notification_names): object_ids = exists_notifications[notification_type.id] notify_tasks = [ t for t in tasks if not (t.id in object_ids or t.is_done) ] if create_notification == notification_type.name: pusher.create_notifications_for_objects(notification_type, today, *notify_tasks) else: for task in notify_tasks: pusher.create_notifications_for_objects( notification_type, task.end_date, task)
def not_done_tasks_notify(tasks): """Notification handling for tasks that moved to active state. It will - create notification for tasks if it's needed - delete all notifications for related cycles """ if not tasks: return cycles = set() declined_tasks = set() for task in tasks: cycles.add(task.cycle) if task.status == models.CycleTaskGroupObjectTask.DECLINED: declined_tasks.add(task) # delete all notifications for cycles about all tasks completed if cycles: pusher.get_notification_query( *(list(cycles)), **{ "notification_names": ["all_cycle_tasks_completed"] }).delete(synchronize_session="fetch") if declined_tasks: pusher.create_notifications_for_objects( pusher.get_notification_type("cycle_task_declined"), datetime.date.today(), *(list(declined_tasks)))
def not_done_tasks_notify(tasks): """Notification handling for tasks that moved to active state. It will - create notification for tasks if it's needed - delete all notifications for related cycles """ if not tasks: return cycles = set() declined_tasks = set() for task in tasks: cycles.add(task.cycle) if task.status == models.CycleTaskGroupObjectTask.DECLINED: declined_tasks.add(task) # delete all notifications for cycles about all tasks completed if cycles: pusher.get_notification_query( *(list(cycles)), **{"notification_names": ["all_cycle_tasks_completed"]} ).delete( synchronize_session="fetch" ) if declined_tasks: pusher.create_notifications_for_objects( pusher.get_notification_type("cycle_task_declined"), datetime.date.today(), *(list(declined_tasks)) )
def handle_cycle_created(obj, manually): today = datetime.date.today() if manually: create_notification = "manual_cycle_created" else: create_notification = "cycle_created" pusher.update_or_create_notifications(obj, today, create_notification) if not obj.is_current: return notification_names = [get_notif_name_by_wf(obj.workflow), create_notification, "cycle_task_overdue", "cycle_task_due_today"] tasks = list(obj.cycle_task_group_object_tasks) query = pusher.get_notification_query( *tasks, **{"notification_names": notification_names}) exists_notifications = collections.defaultdict(set) for notification in query: exists_notifications[notification.notification_type_id].add( notification.object_id) for notification_type in pusher.get_notification_types(*notification_names): object_ids = exists_notifications[notification_type.id] notify_tasks = [t for t in tasks if not (t.id in object_ids or t.is_done)] if create_notification == notification_type.name: pusher.create_notifications_for_objects(notification_type, today, *notify_tasks) else: for task in notify_tasks: pusher.create_notifications_for_objects(notification_type, task.end_date, task)
def done_tasks_notify(tasks): """Notification handling for tasks that moved in done state. It will - delete all notifications for done tasks - create notification for related cycle if all tasks in done state """ if not tasks: return pusher.get_notification_query(*tasks).delete(synchronize_session="fetch") cycle_tasks_dict = collections.defaultdict(list) cycles_dict = {} task_ids = [] for obj in tasks: cycle_tasks_dict[obj.cycle].append(obj) cycles_dict[obj.cycle.id] = obj.cycle task_ids.append(obj.id) task_query = all_models.CycleTaskGroupObjectTask.query.filter( all_models.CycleTaskGroupObjectTask.cycle_id.in_(cycles_dict.keys()), all_models.CycleTaskGroupObjectTask.id.notin_(task_ids), ).options( db.Load(all_models.CycleTaskGroupObjectTask).undefer_group( "CycleTaskGroupObjectTask_complete")).all() for task in task_query: cycle_tasks_dict[cycles_dict[task.cycle_id]].append(task) done_cycles = [ cycle for cycle, cycle_tasks in cycle_tasks_dict.iteritems() if all(task.is_done for task in cycle_tasks) ] pusher.create_notifications_for_objects("all_cycle_tasks_completed", datetime.date.today(), *done_cycles)
def handle_cycle_task_status_change(*objs): """Notification handling for task's status change.""" declined_status = all_models.CycleTaskGroupObjectTask.DECLINED declined_tasks = {obj for obj in objs if obj.status == declined_status} pusher.create_notifications_for_objects( pusher.get_notification_type("cycle_task_declined"), datetime.date.today(), *(declined_tasks) )
def done_tasks_notify(tasks, day): """Notification handling for tasks that moved in done state. It will - delete all notifications for done tasks - create notification for related cycle if all tasks in done state """ if not tasks: return pusher.get_notification_query(*tasks).delete( synchronize_session=False ) cycle_tasks_dict = collections.defaultdict(list) cycles_dict = {} task_ids = [] for obj in tasks: cycle_tasks_dict[obj.cycle].append(obj) cycles_dict[obj.cycle.id] = obj.cycle task_ids.append(obj.id) task_query = all_models.CycleTaskGroupObjectTask.query.filter( all_models.CycleTaskGroupObjectTask.cycle_id.in_(cycles_dict.keys()), all_models.CycleTaskGroupObjectTask.id.notin_(task_ids), ).options( db.Load( all_models.CycleTaskGroupObjectTask ).undefer_group( "CycleTaskGroupObjectTask_complete" ) ).all() for task in task_query: cycle_tasks_dict[cycles_dict[task.cycle_id]].append(task) done_cycles = [cycle for cycle, cycle_tasks in cycle_tasks_dict.iteritems() if all(task.is_done for task in cycle_tasks)] # this filtration is required for correct work of # '/admin/generate_wf_tasks_notifications' endpoint existing_notifications = pusher.get_notification_query( *done_cycles, **{"notification_names": ["all_cycle_tasks_completed"]} ).all() cycles_with_notifications_ids = [notif.object_id for notif in existing_notifications] done_cycles_without_notifs = [cycle for cycle in done_cycles if cycle.id not in cycles_with_notifications_ids] pusher.create_notifications_for_objects("all_cycle_tasks_completed", datetime.date.today(), *done_cycles_without_notifs, day=day)
def handle_cycle_task_created(ctask): """Create notifications on CycleTask POST operation. Args: ctask: CycleTask instance """ notification_types = [get_notif_name_by_wf(ctask.workflow), "cycle_task_due_today", "cycle_task_overdue"] notification_type_query = pusher.get_notification_types(*notification_types) notification_types_dict = {t.name: t for t in notification_type_query} for n_type in notification_types: pusher.create_notifications_for_objects(notification_types_dict[n_type], ctask.end_date, *[ctask])
def not_done_tasks_notify(tasks): """Notification handling for tasks that moved to active state. It will - create notification for tasks if it's needed - delete all notifications for related cycles """ if not tasks: return cycles = set() notification_send_at_tasks_dict = collections.defaultdict(list) notification_types = set() for task in tasks: cycles.add(task.cycle) if task.status == models.CycleTaskGroupObjectTask.DECLINED: notification_send_at_tasks_dict[ ("cycle_task_declined", datetime.date.today()) ].append(task) notification_types.add("cycle_task_declined") for n_type in [get_notif_name_by_wf(task.cycle.workflow), "cycle_task_due_today", "cycle_task_overdue"]: notification_send_at_tasks_dict[ (n_type, task.end_date) ].append(task) notification_types.add(n_type) # delete all notifications for cycles about all tasks compleated and # all tasks notifications that required to be updated pusher.get_notification_query( *(list(cycles) + tasks), **{"notification_names": [ "all_cycle_tasks_completed" ] + list(notification_types)} ).delete( synchronize_session="fetch" ) notification_type_query = pusher.get_notification_types(*notification_types) notification_types_dict = {t.name: t for t in notification_type_query} for pair, pair_tasks in notification_send_at_tasks_dict.iteritems(): notification_type_name, send_at = pair notification_type = notification_types_dict[notification_type_name] pusher.create_notifications_for_objects(notification_type, send_at, *pair_tasks)
def done_tasks_notify(tasks): """Notification handling for tasks that moved in done state. It will - delete all notifications for done tasks - create notification for related cycle if all tasks in done state """ if not tasks: return pusher.get_notification_query(*tasks).delete(synchronize_session="fetch") cycle_tasks_dict = collections.defaultdict(list) cycles_dict = {} task_ids = [] for obj in tasks: cycle_tasks_dict[obj.cycle].append(obj) cycles_dict[obj.cycle.id] = obj.cycle task_ids.append(obj.id) task_query = all_models.CycleTaskGroupObjectTask.query.filter( all_models.CycleTaskGroupObjectTask.cycle_id.in_(cycles_dict.keys()), all_models.CycleTaskGroupObjectTask.id.notin_(task_ids), ).options( db.Load( all_models.CycleTaskGroupObjectTask ).undefer_group( "CycleTaskGroupObjectTask_complete" ) ).all() for task in task_query: cycle_tasks_dict[cycles_dict[task.cycle_id]].append(task) done_cycles = [cycle for cycle, cycle_tasks in cycle_tasks_dict.iteritems() if all(task.is_done for task in cycle_tasks)] pusher.create_notifications_for_objects("all_cycle_tasks_completed", datetime.date.today(), *done_cycles)