burndown.rb 1.93 KB
Newer Older
1
class Burndown
2
  attr_accessor :start_date, :due_date, :end_date, :issues_count, :issues_weight
3 4

  def initialize(milestone)
5 6
    @milestone = milestone
    @start_date = @milestone.start_date
7
    @due_date = @milestone.due_date
8 9
    @end_date = @milestone.due_date
    @end_date = Date.today if @end_date.present? && @end_date > Date.today
10

11
    @issues_count, @issues_weight = milestone.issues.reorder(nil).pluck('COUNT(*), COALESCE(SUM(weight), 0)').first
12 13
  end

14 15
  # Returns the chart data in the following format:
  # [date, issue count, issue weight] eg: [["2017-03-01", 33, 127], ["2017-03-02", 35, 73], ["2017-03-03", 28, 50]...]
16
  def as_json(opts = nil)
17
    return [] unless valid?
18

19 20
    open_issues_count  = issues_count
    open_issues_weight = issues_weight
21

22 23
    start_date.upto(end_date).each_with_object([]) do |date, chart_data|
      closed, reopened = closed_and_reopened_issues_by(date)
24

25 26
      closed_issues_count = closed.count
      closed_issues_weight = sum_issues_weight(closed)
27

28 29 30 31
      open_issues_count -= closed_issues_count
      open_issues_weight -= closed_issues_weight

      chart_data << [date.strftime("%Y-%m-%d"), open_issues_count, open_issues_weight]
32 33 34 35 36 37

      reopened_count = reopened.count
      reopened_weight = sum_issues_weight(reopened)

      open_issues_count += reopened_count
      open_issues_weight += reopened_weight
38
    end
39 40
  end

41
  def valid?
42
    start_date && due_date
43
  end
44

45
  private
46

47
  def sum_issues_weight(issues)
48
    issues.map(&:weight).compact.sum
49 50
  end

51
  def closed_and_reopened_issues_by(date)
52
    current_date = date.to_date
53

54
    closed   = issues_with_closed_at.select { |issue| issue.closed_at.to_date == current_date }
55 56
    reopened = closed.select { |issue| issue.state == 'reopened' }

57
    [closed, reopened]
58
  end
59

60
  def issues_with_closed_at
61
    @issues_with_closed_at ||=
62
      @milestone.issues.select('closed_at, weight, state').
63 64
        where('closed_at IS NOT NULL').
        order('closed_at ASC')
65 66
  end
end