def process_request(self, req): """Collect the data needed for a burndown chart and pass to JavaScript. If the original request was via AJAX we use to_json, otherwise we return data via add_script_data. Remember that our data reflects how a project looked at the end of a day - so if the ticket_bi_historical table has 20 opens tickets on the 1st December, that were 20 open tickets at the end of that day. """ # Get milestone object and all child milestones # we already know it exists, as we checked in the match_request() milestone = Milestone(self.env, req.args['id']) tree = Milestone.build_tree(self.env) all_milestones = [m.name for m in tree.find(milestone.name).traverse()] # If anyone request burndownchart/milestone_id not via AJAX # and not with a format argument (eg when printing) , we redirect to # milestone/milestonename, as we need to load pre_process_request first XMLHttp = req.get_header('X-Requested-With') == 'XMLHttpRequest' if not XMLHttp and 'format' not in req.args: req.redirect(req.href.milestone(milestone.name)) # Calculate series of dates used to render the burn down charts start = self.get_start_date(req, milestone) end = self.get_end_date(milestone) day_before_start = start - timedelta(days=1) dates = self.dates_inbetween(day_before_start, end) # Open a database connection self.log.debug('Connecting to the database to retrieve chart data') db = self.env.get_read_db() # If no metric data is posted, use the project default self.unit_value metric = req.args.get('metric', self.unit_value) # Remaining Effort (aka burndown) Curve remaining_effort_args = [db, all_milestones, day_before_start, end] burndown_series = [] if metric == 'tickets': burndown_series = self.tickets_open_between_dates(*remaining_effort_args) elif metric == 'hours': burndown_series = self.hours_remaining_between_dates(*remaining_effort_args) elif metric == 'points': burndown_series = self.points_remaining_between_dates(*remaining_effort_args) # If we don't have any burndown data send a message and stop if not burndown_series: data = {'result': False} # For ajax request if XMLHttp: req.send(to_json(data), 'text/json') else: return 'burndown_print.html', data, None # Team Effort Curve team_effort = self.team_effort_curve(db, metric, all_milestones, day_before_start, end, self.dates_as_strings(dates)) # Ideal Curve (unit value doesnt matter) if self.ideal_value == 'fixed': original_estimate = burndown_series[0][1] ideal_data = self.ideal_curve(original_estimate, day_before_start, self.get_due_date(milestone)) data = { 'burndowndata': burndown_series, 'teameffortdata' : team_effort, 'idealcurvedata': ideal_data, 'milestone_name': milestone.name, 'start_date': str(day_before_start), 'effort_units': metric, 'yaxix_label': metric.title(), 'result' : True, } # we need some logic to work out the end date on the xAxis data['due_date'] = (self.get_due_date(milestone)).strftime("%Y-%m-%d") # Ajax request if XMLHttp: kwargs = { 'daysback':0, 'ticket':'on', 'ticket_details': 'on', 'ticket_milestone_%s' % Milestone._hash_name(milestone.name): 'on' } data.update({ 'timeline_url': req.href.timeline(kwargs), 'print_burndown': False, 'render_burndown': True, }) req.send(to_json(data), 'text/json') # Normal request (eg the print friendly page) else: if req.args.get('format') == 'print': # Load the burn down JS file and jqPlot library add_script(req, 'burndown/js/burndown.js') self._add_static_files(req) result = {'data': data, 'print_burndown': True, 'render_burndown': True, 'result': True, } add_script_data(req, result) return 'burndown_print.html', result, None