Esempio n. 1
0
def update_cycle_task_group_parent_state(objs):
  """Update cycle status for sent cycle task group"""
  objs = [obj for obj in objs or [] if obj.cycle.workflow.kind != "Backlog"]
  if not objs:
    return
  cycles_dict = {}
  cycle_groups_dict = collections.defaultdict(set)
  group_ids = []
  for obj in objs:
    cycle_groups_dict[obj.cycle].add(obj)
    group_ids.append(obj.id)
    cycles_dict[obj.cycle.id] = obj.cycle
  # collect all groups that are in same cycles that group from sent list
  groups = models.CycleTaskGroup.query.filter(
      models.CycleTaskGroup.cycle_id.in_([c.id for c in cycle_groups_dict]),
  ).options(
      orm.undefer_group("CycleTaskGroup_complete")
  ).distinct().with_for_update().all()
  for group in groups:
    cycle_groups_dict[cycles_dict[group.cycle_id]].add(group)

  updated_cycles = []
  for cycle in cycles_dict.itervalues():
    old_status = cycle.status
    _update_parent_status(cycle, {g.status for g in cycle_groups_dict[cycle]})
    cycle.start_date, cycle.end_date = _get_date_range(
        cycle_groups_dict[cycle])
    cycle.next_due_date = _get_min_next_due_date(cycle_groups_dict[cycle])
    if old_status != cycle.status:
      updated_cycles.append(Signals.StatusChangeSignalObjectContext(
          instance=cycle, old_status=old_status, new_status=cycle.status))
  if updated_cycles:
    Signals.status_change.send(models.Cycle, objs=updated_cycles)
Esempio n. 2
0
def handle_cycle_task_group_object_task_put(
        sender, obj=None, src=None, service=None):  # noqa pylint: disable=unused-argument
  if inspect(obj).attrs.status.history.has_changes():
    # TODO: check why update_cycle_object_parent_state destroys object history
    # when accepting the only task in a cycle. The listener below is a
    # workaround because of that.
    Signals.status_change.send(
        obj.__class__,
        objs=[
            Signals.StatusChangeSignalObjectContext(
                instance=obj,
                new_status=obj.status,
                old_status=inspect(obj).attrs.status.history.deleted[0],
            )
        ]
    )

  # Doing this regardless of status.history.has_changes() is important in order
  # to update objects that have been declined. It updates the os_last_updated
  # date and last_updated_by.
  if getattr(obj.task_group_task, 'object_approval', None):
    for tgobj in obj.task_group_task.task_group.objects:
      if obj.status == 'Verified':
        tgobj.modified_by = get_current_user()
        tgobj.set_reviewed_state()
    db.session.flush()
Esempio n. 3
0
def update_cycle_task_child_state(obj):
  """Update child attributes state of cycle task

  Args:
    obj: Cycle task instance
  """
  status_order = (None, 'Assigned', 'InProgress',
                  'Declined', 'Finished', 'Verified')
  status = obj.status
  children_attrs = _cycle_task_children_attr.get(type(obj), [])
  for children_attr in children_attrs:
    if children_attr:
      children = getattr(obj, children_attr, None)
      for child in children:
        if status == 'Declined' or \
           status_order.index(status) > status_order.index(child.status):
          if is_allowed_update(child.__class__.__name__,
                               child.id, child.context.id):
            old_status = child.status
            child.status = status
            Signals.status_change.send(
                child.__class__,
                objs=[
                    Signals.StatusChangeSignalObjectContext(
                        instance=child,
                        new_status=child.status,
                        old_status=old_status,
                    )
                ]
            )
          update_cycle_task_child_state(child)
Esempio n. 4
0
def update_cycle_task_group_parent_state(objs):
  """Update cycle status for sent cycle task group"""
  objs = [obj for obj in objs or [] if obj.cycle.workflow.kind != "Backlog"]
  if not objs:
    return
  cycles_dict = {}
  cycle_statuses_dict = collections.defaultdict(set)
  group_ids = []
  for obj in objs:
    cycle_statuses_dict[obj.cycle].add(obj.status)
    group_ids.append(obj.id)
    cycles_dict[obj.cycle.id] = obj.cycle
  # collect all groups that are in same cycles that group from sent list
  child_statuses = models.CycleTaskGroup.query.filter(
      models.CycleTaskGroup.cycle_id.in_([c.id for c in cycle_statuses_dict]),
      models.CycleTaskGroup.id.notin_(group_ids)
  ).distinct().with_for_update()
  for cycle_id, status in child_statuses.values("cycle_id", "status"):
    cycle_statuses_dict[cycles_dict[cycle_id]].add(status)

  updated_cycles = []
  for cycle, group_statuses in cycle_statuses_dict.iteritems():
    old_status = cycle.status
    _update_parent_state(cycle, group_statuses)
    if old_status != cycle.status:
      updated_cycles.append(Signals.StatusChangeSignalObjectContext(
          instance=cycle, old_status=old_status, new_status=cycle.status))
  if updated_cycles:
    Signals.status_change.send(models.Cycle, objs=updated_cycles)
Esempio n. 5
0
def update_cycle_task_object_task_parent_state(objs):
  """Update cycle task group status for sent cycle task"""
  objs = [o for o in objs or [] if o.cycle.workflow.kind != "Backlog"]
  if not objs:
    return
  groups_dict = {i.cycle_task_group_id: i.cycle_task_group for i in objs}
  group_status_dict = collections.defaultdict(set)
  # load all tasks that are in the same groups there are tasks that be updated
  task_ids = [t.id for t in db.session.deleted
              if isinstance(t, models.CycleTaskGroupObjectTask)]
  for task in itertools.chain(db.session.dirty, db.session.new):
    if not isinstance(task, models.CycleTaskGroupObjectTask):
      continue
    group_status_dict[task.cycle_task_group].add(task.status)
    if task.id:
      task_ids.append(task.id)
  query = models.CycleTaskGroupObjectTask.query.filter(
      models.CycleTaskGroupObjectTask.cycle_task_group_id.in_(groups_dict)
  )
  if task_ids:
    query = query.filter(models.CycleTaskGroupObjectTask.id.notin_(task_ids))
  query = query.distinct().with_for_update()
  for group_id, status in query.values("cycle_task_group_id", "status"):
    group_status_dict[groups_dict[group_id]].add(status)
  updated_groups = []
  for group, task_statuses in group_status_dict.iteritems():
    old_status = group.status
    _update_parent_state(group, task_statuses)
    if old_status != group.status:
      # if status updated then add it in list. require to update cycle state
      updated_groups.append(Signals.StatusChangeSignalObjectContext(
          instance=group, old_status=old_status, new_status=group.status))
  if updated_groups:
    Signals.status_change.send(models.CycleTaskGroup, objs=updated_groups)
    update_cycle_task_group_parent_state([i.instance for i in updated_groups])
Esempio n. 6
0
def handle_cycle_task_group_object_task_post(
        sender, obj=None, src=None, service=None):  # noqa pylint: disable=unused-argument
  Signals.status_change.send(
      obj.__class__,
      objs=[
          Signals.StatusChangeSignalObjectContext(
              instance=obj,
              new_status=obj.status,
              old_status=None,
          )
      ]
  )
  db.session.flush()
Esempio n. 7
0
def handle_cycle_task_group_object_task_put(
        sender, obj=None, src=None, service=None):  # noqa pylint: disable=unused-argument
  if inspect(obj).attrs.status.history.has_changes():
    # TODO: check why update_cycle_object_parent_state destroys object history
    # when accepting the only task in a cycle. The listener below is a
    # workaround because of that.
    Signals.status_change.send(
        obj.__class__,
        objs=[
            Signals.StatusChangeSignalObjectContext(
                instance=obj,
                new_status=obj.status,
                old_status=inspect(obj).attrs.status.history.deleted[0],
            )
        ]
    )
Esempio n. 8
0
def handle_cycle_task_group_object_task_post(
        sender, obj=None, src=None, service=None):  # noqa pylint: disable=unused-argument
  if obj.cycle.workflow.kind != "Backlog":
    for person_id in obj.get_person_ids_for_rolename("Task Assignees"):
      ensure_assignee_is_workflow_member(obj.cycle.workflow, None, person_id)
  update_cycle_dates(obj.cycle)

  Signals.status_change.send(
      obj.__class__,
      objs=[
          Signals.StatusChangeSignalObjectContext(
              instance=obj,
              new_status=obj.status,
              old_status=None,
          )
      ]
  )
  db.session.flush()