def sprintInfoPost(handler, id, p_name, p_start, p_end, p_goals, p_members = None, p_clear = [], p_private = False, p_hidden = False): def die(msg): print msg done() handler.wrappers = False if not handler.session['user']: die("You must be logged in to modify sprint info") id = to_int(id, 'id', die) p_members = to_int(p_members, 'members', die) sprint = Sprint.load(id) if not sprint or sprint.isHidden(handler.session['user']): die("There is no sprint with ID %d" % id) if sprint.owner != handler.session['user']: die("You must be the scrummaster to modify sprint information") try: start = re.match("^(\d{1,2})/(\d{1,2})/(\d{4})$", p_start) if not start: raise ValueError month, day, year = map(int, start.groups()) start = datetime(year, month, day, 0, 0, 0) except ValueError: die("Malformed start date: %s" % stripTags(p_start)) try: end = re.match("^(\d{1,2})/(\d{1,2})/(\d{4})$", p_end) if not end: raise ValueError month, day, year = map(int, end.groups()) end = datetime(year, month, day, 23, 59, 59) except ValueError: die("Malformed end date: %s" % stripTags(p_end)) msg = Sprint.validateDates(start, end, tsToDate(sprint.start), tsToDate(sprint.end)) if msg: die(msg) goals = map(Goal.load, to_int(p_goals.keys(), 'goals', die)) if not all(goals): die("One or more goals do not exist") members = set(map(User.load, p_members)) if p_members else set() if not all(members): die("One or more members do not exist") if sprint.owner not in members: die("The scrummaster (%s) must be a sprint member" % sprint.owner) tasks = sprint.getTasks() changedTasks = set() avail = Availability(sprint) addMembers = set(members) - set(sprint.members) delMembers = set(sprint.members) - set(members) for user in delMembers: for task in filter(lambda task: user in task.assigned, tasks): print "Removing %s from %d<br>" % (user, task.id) task.assigned -= {user} if len(task.assigned) == 0: print "Adding %s to %d<br>" % (sprint.owner, task.id) task.assigned = {sprint.owner} changedTasks.add(task) avail.delete(user) sprint.members -= {user} # For event dispatching changes = OrderedDict([ ('name', None if sprint.name == p_name else p_name), ('start', None if tsToDate(sprint.start) == start else start), ('end', None if tsToDate(sprint.end) == end else end), ('addMembers', addMembers), ('delMembers', delMembers), # Updated later ('addGoals', []), ('removeGoals', []), ('addFlags', []), ('removeFlags', []), ]) sprint.members |= addMembers sprint.name = p_name p_private = (p_private or p_hidden) # Hidden implies Private for flagName, flagValue in (('private', p_private), ('hidden', p_hidden)): if flagValue and flagName not in sprint.flags: sprint.flags.add(flagName) changes['addFlags'].append(flagName) elif not flagValue and flagName in sprint.flags: sprint.flags.remove(flagName) changes['removeFlags'].append(flagName) if dateToTs(start) != sprint.start or dateToTs(end) != sprint.end: sprint.start = dateToTs(start) sprint.end = dateToTs(end) avail.trim() sprint.save() for id in p_goals: goal = Goal.load(int(id)) if goal.name != p_goals[id]: if goal.name: changes['removeGoals'].append(goal.name) if p_goals[id]: changes['addGoals'].append(p_goals[id]) goal.name = p_goals[id] goal.save() if start: for task in sprint.getTasks(includeDeleted = True): for rev in task.getRevisions(): if rev.timestamp < sprint.start: rev.timestamp = sprint.start rev.save() else: break for task in changedTasks: if task.timestamp < sprint.start: task.timestamp = sprint.start if p_clear: ids = [to_int(goalid, 'p_clear', die) for goalid in p_clear] for task in tasks: if task.goal and task.goal.id in ids: task.goal = None changedTasks.add(task) for task in changedTasks: print "Saving new revision for %d<br>" % task.id task.saveRevision(handler.session['user']) handler.responseCode = 299 delay(handler, SuccessBox("Updated info", close = 3, fixed = True)) Event.sprintInfoUpdate(handler, sprint, changes)