├── .gitignore
├── README.rdoc
├── app
├── controllers
│ ├── dchbxreports_controller.rb
│ └── reports_controller.rb
├── helpers
│ ├── dchbxreports_helper.rb
│ └── reports_helper.rb
└── views
│ ├── dchbxreports
│ ├── duedates.html.erb
│ ├── index.html.erb
│ ├── quarter.html.erb
│ ├── sla.html.erb
│ ├── stakeholders.html.erb
│ ├── status.erb
│ ├── userHoldUp.html.erb
│ ├── useractivity.html.erb
│ ├── usersReturnForDef.html.erb
│ └── velocity.html.erb
│ ├── reports
│ └── sla.html.erb
│ └── settings
│ └── _report_settings.html.erb
├── assets
└── images
│ └── reports.png
├── config
├── locales
│ └── en.yml
└── routes.rb
├── init.rb
└── test
├── functional
├── dchbxreports_controller_test.rb
└── reports_controller_test.rb
└── test_helper.rb
/.gitignore:
--------------------------------------------------------------------------------
1 | # Make sure no sensitive data is accidentally committed
2 | # add w/ git add --force if actually docs
3 | *.csv
4 | *.txt
5 | *.xml
6 | *.xls
7 | *.xlst
8 | *.xlsx
9 | *.doc
10 | *.docx
11 |
--------------------------------------------------------------------------------
/README.rdoc:
--------------------------------------------------------------------------------
1 | = redmine_reports
2 |
3 | Description goes here
4 |
5 | == License
6 |
7 | The software is available as open source under the terms of the MIT License (MIT)
8 |
9 | Developed and managed by IdeaCrew, Inc. and HBX
10 |
11 | Permission is hereby granted, free of charge, to any person obtaining a copy
12 | of this software and associated documentation files (the "Software"), to deal
13 | in the Software without restriction, including without limitation the rights
14 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 | copies of the Software, and to permit persons to whom the Software is
16 | furnished to do so, subject to the following conditions:
17 |
18 | The above attribution notice and this permission notice shall be included in
19 | all copies or substantial portions of the Software.
20 |
21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27 | THE SOFTWARE.
28 |
--------------------------------------------------------------------------------
/app/controllers/dchbxreports_controller.rb:
--------------------------------------------------------------------------------
1 | class DchbxreportsController < ApplicationController
2 | unloadable
3 | helper :queries
4 | include QueriesHelper
5 |
6 | def index
7 | @cq = IssueQuery.where(visibility: 2).order('project_id ASC')
8 | end
9 |
10 | def velocity
11 | @output = {}
12 | @output['totalIssuesWithWBSandStoryPoints'] = IssueQuery.find(208)
13 | end
14 |
15 | def usersReturnForDef
16 | @output = {}
17 | journalDetails = JournalDetail.where(value: 6).where(property: "attr").where(prop_key: "status_id")
18 | journalDetails.each do |jd|
19 | user_id = false
20 | jd.journal.details.where(prop_key: 'assigned_to_id').each do |jd_user|
21 | user_id = jd_user.value
22 | end
23 | unless user_id == false
24 | if @output[user_id].nil?
25 | @output[user_id] = {}
26 | @output[user_id]['issue_count'] = {};
27 | JournalDetail.where(value: user_id).where(property: "attr").where(prop_key: "assigned_to_id").each do |jdd|
28 | @output[user_id]['issue_count'][jdd.journal.journalized_id] = true;
29 | end
30 | @output[user_id]['rfd_count'] = 1
31 | elsif @output[user_id]['rfd_count'].nil?
32 | @output[user_id]['rfd_count'] = 1
33 | else
34 | @output[user_id]['rfd_count'] = @output[user_id]['rfd_count'] + 1
35 | end
36 | end
37 | end
38 | @output.each do |user_id,user_info|
39 | @output[user_id]['user'] = User.where(id: user_id).where(status: 1).first
40 | @output[user_id]['issue_count'] = @output[user_id]['issue_count'].count()
41 | @output[user_id]['per'] = (@output[user_id]['rfd_count'].to_f / @output[user_id]['issue_count'].to_f ) * 100
42 | end
43 | ## figure out thrashing per issue
44 | @issueOut = {}
45 | Issue.where(closed_on: nil).where(project_id:[24,94]).each do |issue|
46 | @issueOut[issue.id] = {}
47 | @issueOut[issue.id]['thrashCount'] = 0
48 | @issueOut[issue.id]['issue'] = issue
49 | issue.journals.each do |journal|
50 | @issueOut[issue.id]['thrashCount'] = @issueOut[issue.id]['thrashCount'] + journal.details.where(prop_key:'status_id').where(property: "attr").where(value:[9,33,28,6,8,4]).count
51 | end
52 | end
53 | @issueOut.sort_by {|key,value| value['thrashCount'].to_i }
54 | end
55 |
56 | def duedates
57 | @output = {
58 | 'Issues Not Started Past Start Date' => {
59 | 'total' => {
60 | 'query_id' => 190,
61 | },
62 | 'left' => {
63 | 'query_id' => 191,
64 | }
65 | },
66 | 'Issues Past Due' =>{
67 | 'total' => {
68 | 'query_id' => 188
69 | },
70 | 'left' => {
71 | 'query_id' => 189
72 | }
73 | },
74 | 'Issues Closed' => {
75 | 'total' => {
76 | 'query_id' => 192
77 | }
78 | },
79 | 'Issues In Flight' => {
80 | 'total' => {
81 | 'query_id' => 195
82 | }
83 | }
84 | }
85 | @output.each do |barTitle,barPercents|
86 | unless @output[barTitle]['total'].nil?
87 | @output[barTitle]['total']['query'] = IssueQuery.find(@output[barTitle]['total']['query_id'])
88 | @output[barTitle]['total']['issue_count'] = @output[barTitle]['total']['query'].issue_count
89 | end
90 | unless @output[barTitle]['left'].nil?
91 | @output[barTitle]['left']['query'] = IssueQuery.find(@output[barTitle]['left']['query_id'])
92 | @output[barTitle]['left']['issue_count'] = @output[barTitle]['left']['query'].issue_count
93 | ##figure out percents!
94 | @output[barTitle]['percentDone'] = ( @output[barTitle]['left']['issue_count'].to_f / @output[barTitle]['total']['issue_count'].to_f ) * 100
95 | @output[barTitle]['percentLeft'] = 100 - @output[barTitle]['percentDone'].to_f
96 | end
97 | end
98 | ##bottom issue list
99 | @issueList = Issue.where(project_id:94).where(fixed_version_id:107).order('status_id').order('updated_on DESC')
100 | @bugIssueList = Issue.where(project_id:24).order('status_id')
101 | end
102 |
103 | # def stakeholders
104 | # issueStatusIdForStakeholderReview = 8
105 | # @issuesInStakeholderReview = Issue.where('status_id = ?', issueStatusIdForStakeholderReview).order('assigned_to_id ASC, id ASC')
106 | # end
107 |
108 | def sla
109 | ## This can help us tell if an issue is closed or not
110 | issueStatus = IssueStatus.all
111 | ## This gives us all the issues, to make sure we don't have to call the db X times
112 | @projects_to_track = [12,26,33,20,21,22,16,23,24,94,98,97,25]
113 | issues = Issue.where(project_id: @projects_to_track)
114 | ## Trackers
115 | trackers = Tracker.all
116 | ## Issue priorities
117 | issuePriorities = Enumeration.where("type = 'IssuePriority'")
118 | ##processed var we pass to view
119 | @slaReport = {}
120 | ## run over each issue, and each sla, to generate our data
121 | Setting.plugin_redmine_reports['slas'].each_with_index do |sla,id|
122 | @slaReport[id] = {}
123 | @slaReport[id]['type'] = sla['type']
124 | @slaReport[id]['id'] = sla['id']
125 | @slaReport[id]['timeToResolve'] = sla['timeToResolve']
126 | @slaReport[id]['daysToResolve'] = sla['timeToResolve'] / (24*60*60)
127 | @slaReport[id]['totalIssues'] = 0
128 | @slaReport[id]['closedIssues'] = 0
129 | @slaReport[id]['closedIssuesInProgressTime'] = 0
130 | @slaReport[id]['openInSlaIssues'] = 0
131 | @slaReport[id]['openPastSlaIssues'] = 0
132 |
133 | ##find the name of the SLA we are tracking
134 | if sla['type'] == "trackers"
135 | trackers.each do |tracker|
136 | if tracker.id.to_i == sla['id'].to_i
137 | @slaReport[id]['name'] = "Tracker: #{tracker.name}"
138 | end
139 | end
140 | end
141 | if sla['type'] == "enumerations"
142 | issuePriorities.each do |pri|
143 | if pri['id'].to_i == sla['id'].to_i
144 | @slaReport[id]['name'] = "Priority: #{pri.name}"
145 | end
146 | end
147 | end
148 | if sla['type'] == "issue_status"
149 | myIssueName = IssueStatus.where('id = ?',sla['id'].to_i).first.name
150 | @slaReport[id]['name'] = "Issue Status: #{myIssueName}"
151 | end
152 | ##loop our issues and find our data
153 | issues.each do |issue|
154 | if (
155 | sla['type'] == "trackers" &&
156 | issue['tracker_id'].to_i == sla['id'].to_i
157 | ) ||
158 | (
159 | sla['type'] == "enumerations" &&
160 | issue['priority_id'].to_i == sla['id'].to_i
161 | ) ||
162 | (
163 | sla['type'] == "issue_status" &&
164 | issue['status_id'].to_i == sla['id'].to_i
165 | )
166 | ##figure out if the issue is currently closed or not
167 | issueIsClosed = false
168 | issueStatus.each do |status|
169 | if issue['status_id'].to_i == status['id'].to_i
170 | if status.is_closed
171 | issueIsClosed = true
172 | if issue['closed_on'].to_i > Time.new.to_i - Setting.plugin_redmine_reports['slaShowProgressTime'].to_i
173 | @slaReport[id]['closedIssuesInProgressTime'] = @slaReport[id]['closedIssuesInProgressTime'] + 1
174 | end
175 | end
176 | end
177 | end
178 | ##figure out if the issue is in our SLA period
179 | if issueIsClosed == false
180 | if to_boolean(sla['sinceCreation'])
181 | timeSince = issue['created_on'].beginning_of_day.to_i + sla['timeToResolve'].to_i
182 | else
183 | timeSince = issue['updated_on'].beginning_of_day.to_i + sla['timeToResolve'].to_i
184 | end
185 | if timeSince < Time.new.to_i
186 | @slaReport[id]['openPastSlaIssues'] = @slaReport[id]['openPastSlaIssues'] + 1
187 | else
188 | @slaReport[id]['openInSlaIssues'] = @slaReport[id]['openInSlaIssues'] + 1
189 | end
190 | else
191 | @slaReport[id]['closedIssues'] = @slaReport[id]['closedIssues'] + 1
192 | end
193 | ##record our total number of issues for this sla
194 | @slaReport[id]['totalIssues'] = @slaReport[id]['totalIssues'] + 1
195 | end
196 | end
197 | end
198 | end
199 |
200 |
201 | def status
202 | @issueStatuses = IssueStatus.where('is_closed = ?', false)
203 | @users = User.all()
204 | @issues = {}
205 | @issueStatuses.each do |status|
206 | @issues[status['id']] = Issue.where('closed_on IS NULL').where('status_id = ?',status['id']).where(project_id: [24,94]).order('updated_on ASC')
207 | end
208 | end
209 |
210 | def userHoldUp
211 | @userStats = {}
212 | issueStatus = IssueStatus.all
213 | users = User.where('status = 1').order(:lastname)
214 | ##users = User.where('status = ?','active').or('status = ?', 'registered')
215 | users.each do |user|
216 | totalWaitTime = 0
217 | userIssues = {}
218 | issues = Issue.where("assigned_to_id = ?",user['id']).where(project_id: [24,94])
219 | issues.each do |issue|
220 | ##figure out if the issue is currently closed or not
221 | issueIsClosed = false
222 | issueStatus.each do |status|
223 | if issue['status_id'].to_i == status['id'].to_i
224 | if status.is_closed
225 | issueIsClosed = true
226 | end
227 | end
228 | end
229 | if issueIsClosed == false
230 | totalWaitTime = totalWaitTime + (Time.new.to_i - issue['updated_on'].to_i)
231 | userIssues[i] = issue
232 | end
233 | end
234 | @userStats[user['id'].to_s] = {
235 | 'user' => user,
236 | 'totalWaitTime' => totalWaitTime,
237 | 'issues' => userIssues,
238 | }
239 | end
240 | ##@userStats.sort! { |a,b| a['totalWaitTime'] <=> b['totalWaitTime'] }
241 | end
242 | private
243 | def i
244 | @i ||= -1
245 | @i += 1
246 | end
247 | def to_boolean(str)
248 | str == 'true'
249 | end
250 | end
251 |
--------------------------------------------------------------------------------
/app/controllers/reports_controller.rb:
--------------------------------------------------------------------------------
1 | class ReportsController < ApplicationController
2 | unloadable
3 |
4 | def index
5 | p 'index'
6 | end
7 |
8 | def sla
9 | p 'sla'
10 | end
11 |
12 |
13 |
14 | end
15 |
--------------------------------------------------------------------------------
/app/helpers/dchbxreports_helper.rb:
--------------------------------------------------------------------------------
1 | module DchbxreportsHelper
2 | end
3 |
--------------------------------------------------------------------------------
/app/helpers/reports_helper.rb:
--------------------------------------------------------------------------------
1 | module ReportsHelper
2 | end
3 |
--------------------------------------------------------------------------------
/app/views/dchbxreports/duedates.html.erb:
--------------------------------------------------------------------------------
1 | <% content_for :header_tags do %>
2 | <%= stylesheet_link_tag 'tooltipster/dist/css/tooltipster.bundle.min.css', :plugin => 'redmine_user_priority' %>
3 | <%= stylesheet_link_tag 'tooltipster/dist/css/plugins/tooltipster/sideTip/themes/tooltipster-sideTip-shadow.min.css', :plugin => 'redmine_user_priority' %>
4 | <%= javascript_include_tag 'tooltipster/dist/js/tooltipster.bundle.min.js', :plugin => 'redmine_user_priority' %>
5 | <% end %>
6 |
7 |
17 |
18 |
41 |
42 |
Progress Report for Project hbx_enroll_2016_roadmap
43 | <% @output.each do |barTitle,barInfo| %>
44 |
72 | <% end %>
73 |
74 |
75 |
76 |
92 | Enroll Roadmap Tickets for Q4
93 |
94 | <% currentStatusId = false %>
95 | <% @issueList.each do |issue| %>
96 | <% unless currentStatusId == issue.status_id %>
97 | <% unless currentStatusId == false %>
98 |
99 | <% end %>
100 |
101 |
<%= issue.status.name %>
102 | <% currentStatusId = issue.status_id %>
103 | <% end %>
104 |
109 | <% end %>
110 |
111 |
112 |
113 |
114 | Enroll Bugs and Maintance Tickets
115 |
116 | <% currentStatusId = false %>
117 | <% @bugIssueList.each do |issue| %>
118 | <% unless currentStatusId == issue.status_id %>
119 | <% unless currentStatusId == false %>
120 |
121 | <% end %>
122 |
123 |
<%= issue.status.name %>
124 | <% currentStatusId = issue.status_id %>
125 | <% end %>
126 |
131 | <% end %>
132 |
133 |
134 |
135 |
--------------------------------------------------------------------------------
/app/views/dchbxreports/index.html.erb:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 |
Custom Queries
19 |
20 | <% current_project_id = false %>
21 | <% @cq.each do |q| %>
22 | <% unless current_project_id == q.project_id %>
23 | <% unless current_project_id == false %>
24 |
25 | <% end %>
26 | <% current_project_id = q.project_id %>
27 | <% if q.project_id.nil? %>
28 |
GLOBAL
44 |
45 |
46 |
59 |
60 |
61 |
External Reports
62 |
69 |
70 |
--------------------------------------------------------------------------------
/app/views/dchbxreports/quarter.html.erb:
--------------------------------------------------------------------------------
1 | DchbxreportsController#quarter
2 |
--------------------------------------------------------------------------------
/app/views/dchbxreports/sla.html.erb:
--------------------------------------------------------------------------------
1 |
86 |
87 | SLA Report
88 |
89 | <% @slaReport.each_with_index do |sla,id| %>
90 |
91 |
92 | <%= sla[1]['name'] %> - <%= sla[1]['daysToResolve'] %> Days
93 |
94 | <% if sla[1]['totalIssues'] > 0 %>
95 | <% percentClosed = ( (sla[1]['closedIssues'].to_f - sla[1]['closedIssuesInProgressTime'].to_f )/ sla[1]['totalIssues'].to_f ) * 100 %>
96 | <% percentClosedLastSevenDays = ( sla[1]['closedIssuesInProgressTime'].to_f / sla[1]['totalIssues'].to_f ) * 100 %>
97 | <% percentOpenInSLA = ( sla[1]['openInSlaIssues'].to_f / sla[1]['totalIssues'].to_f ) * 100 %>
98 | <% percentOpenPassSla = ( sla[1]['openPastSlaIssues'].to_f / sla[1]['totalIssues'].to_f ) * 100 %>
99 |
100 |
101 |
102 | |
103 | |
104 | |
105 | |
106 |
107 |
108 |
109 |
110 |
111 |
112 | Total: <%= sla[1]['totalIssues'] %>
113 |
114 |
115 | Closed: <%= sla[1]['closedIssues'] %>
116 |
117 |
118 | Closed [ in last <%= distance_of_time_in_words(Setting.plugin_redmine_reports['slaShowProgressTime'].to_i).upcase %> ]: <%= sla[1]['closedIssuesInProgressTime'] %>
119 |
120 |
121 | Open [ in sla ]: <%= sla[1]['openInSlaIssues'] %>
122 |
123 |
134 |
135 | <% else %>
136 |
No issues are under this sla.
137 | <% end %>
138 |
139 |
140 |
141 | <% end %>
142 |
143 |
144 |
--------------------------------------------------------------------------------
/app/views/dchbxreports/stakeholders.html.erb:
--------------------------------------------------------------------------------
1 |
12 |
13 |
14 |
Stakeholders and Their Issues
15 | <% lastAssignedToId = "adkfj" %>
16 | <% @issuesInStakeholderReview.each do |issue| %>
17 | <% if issue.assigned_to_id != lastAssignedToId %>
18 |
19 | <% if issue.assigned_to_id.nil? %>
20 | nobody
21 | <% else %>
22 | <%= issue.assigned_to.firstname %> <%= issue.assigned_to.lastname %>
23 | <% end %>
24 |
25 | <% lastAssignedToId = issue.assigned_to_id %>
26 | <% end %>
27 |
28 |
<%=issue.id%>: Last Updated <%=distance_of_time_in_words(Time.new.to_i - issue.updated_on.to_i) %> ago: <%= issue.subject %>
29 |
30 | <% end %>
31 |
32 |
--------------------------------------------------------------------------------
/app/views/dchbxreports/status.erb:
--------------------------------------------------------------------------------
1 | <% content_for :header_tags do %>
2 | <%= stylesheet_link_tag 'tooltipster/dist/css/tooltipster.bundle.min.css', :plugin => 'redmine_user_priority' %>
3 | <%= stylesheet_link_tag 'tooltipster/dist/css/plugins/tooltipster/sideTip/themes/tooltipster-sideTip-shadow.min.css', :plugin => 'redmine_user_priority' %>
4 | <%= javascript_include_tag 'tooltipster/dist/js/tooltipster.bundle.min.js', :plugin => 'redmine_user_priority' %>
5 | <% end %>
6 |
7 |
18 |
19 |
54 |
55 | Issue Status's
56 | Shows the top 10 longest time since updated issues for each status
57 |
58 |
59 | <% @issueStatuses.each do |status| %>
60 |
61 |
62 | <%= status.name %>
63 |
64 | <% @issues[status['id']].first(10).each do |issue| %>
65 | <% issueAssignee = "nobody" %>
66 | <% @users.each do |user| %>
67 | <% if user['id'] == issue['assigned_to_id'] %>
68 | <% issueAssignee = "#{user['firstname']} #{user['lastname']}" %>
69 | <% end %>
70 | <% end %>
71 |
91 |
94 | <% end %>
95 |
96 |
97 | <% end %>
98 |
99 |
100 |
--------------------------------------------------------------------------------
/app/views/dchbxreports/userHoldUp.html.erb:
--------------------------------------------------------------------------------
1 |
13 | Average User Hold Up
14 |
15 |
16 |
17 | Last Name |
18 | First Name |
19 | Avg Wait Time |
20 | Total Wait Time |
21 | Total Assigned Issues |
22 |
23 |
24 | <% @userStats.each do |user| %>
25 | <%
26 | avgWaitTime = 0
27 | avgWaitTimeString = ""
28 | totalWaitTimeString = ""
29 | if user[1]['issues'].count > 0
30 | avgWaitTime = user[1]['totalWaitTime'] / user[1]['issues'].count
31 | avgWaitTimeString = distance_of_time_in_words(avgWaitTime)
32 | totalWaitTimeString = distance_of_time_in_words(user[1]['totalWaitTime'])
33 | end
34 | unless user[1]['issues'].count == 0
35 | %>
36 |
37 | <%= user[1]['user']['lastname'] %> |
38 | <%= user[1]['user']['firstname'] %> |
39 | <%= avgWaitTimeString %> |
40 | <%= totalWaitTimeString %> |
41 |
42 |
43 | <%= user[1]['issues'].count %>
44 |
45 | |
46 |
47 | <% end %>
48 | <% end %>
49 |
50 |
51 |
52 | * Note that all stats listed above are from current OPEN issues.
53 |
--------------------------------------------------------------------------------
/app/views/dchbxreports/useractivity.html.erb:
--------------------------------------------------------------------------------
1 | <%= debug @output %>
2 |
--------------------------------------------------------------------------------
/app/views/dchbxreports/usersReturnForDef.html.erb:
--------------------------------------------------------------------------------
1 |
20 |
21 | <% @output.each do |user_id,user_info| %>
22 | <% unless user_info['user'].nil? || user_info['user']['firstname'] == "" %>
23 |
24 |
25 | <%=user_info['user']['firstname'] %> <%=user_info['user']['lastname'] %>
26 |
27 |
28 |
29 | # of RFDs: <%=user_info['rfd_count'] %>
30 |
31 |
32 | # of Issues: <%=user_info['issue_count'] %>
33 |
34 |
35 | % RFD: <%=user_info['per'].to_i%>%
36 |
37 |
38 |
39 | <% end %>
40 | <% end %>
41 |
42 | By Issue
43 | <% @issueOut.each do |issue_id,info| %>
44 | <% if info['thrashCount'].to_i > 9 %>
45 |
50 | <% end %>
51 | <% end %>
52 |
--------------------------------------------------------------------------------
/app/views/dchbxreports/velocity.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 | <%
9 | teamGroups = Setting.plugin_redmine_user_priority['rup_teamGroups'].split(/\s*,\s*/)
10 | totalIssueCount = @output['totalIssuesWithWBSandStoryPoints'].issue_count
11 | chart_labels = "["
12 | chart_openTicketsData = "["
13 | chart_closedTicketsData = "["
14 | weekOf = Date.today.beginning_of_quarter.beginning_of_week
15 | chart_teamBurndown = {}
16 | teamGroups.each do |team|
17 | chart_teamBurndown[team] = {}
18 | chart_teamBurndown[team]['openTicketsData'] = "["
19 | chart_teamBurndown[team]['closedTicketsData'] = "["
20 | end
21 | while weekOf < Date.today.end_of_quarter.end_of_week do
22 | startTime = weekOf
23 | endTime = weekOf + 2.weeks
24 | chart_labels << "\"#{startTime.strftime("%m/%d")} - #{endTime.strftime("%m/%d")}\", "
25 | openIssues = 0
26 | closedIssues = 0
27 | teamBurndown = {}
28 | teamGroups.each do |team|
29 | teamBurndown[team] = {}
30 | teamBurndown[team]['open'] = 0
31 | teamBurndown[team]['closed'] = 0
32 | end
33 | @output['totalIssuesWithWBSandStoryPoints'].issues.each do |issue|
34 | if issue.closed_on.nil? || issue.closed_on > startTime
35 | openIssues = openIssues + issue.custom_values.where(custom_field_id:24).first.value.to_i
36 | else
37 | closedIssues = closedIssues + issue.custom_values.where(custom_field_id:24).first.value.to_i
38 | end
39 | issue.assigned_to.groups.each do |group|
40 | if teamGroups.include? group.id.to_s
41 | if issue.closed_on.nil? || issue.closed_on > startTime
42 | teamBurndown[group.id.to_s]['open'] = teamBurndown[group.id.to_s]['open'] + issue.custom_values.where(custom_field_id:24).first.value.to_i
43 | else
44 | teamBurndown[group.id.to_s]['closed'] = teamBurndown[group.id.to_s]['closed'] + issue.custom_values.where(custom_field_id:24).first.value.to_i
45 | end
46 | end
47 | end
48 | end
49 | chart_openTicketsData << "\"#{openIssues.to_s}\","
50 | chart_closedTicketsData << "\"#{closedIssues.to_s}\","
51 | teamGroups.each do |team|
52 | chart_teamBurndown[team]['openTicketsData'] << "\"#{teamBurndown[team]['open'].to_s}\","
53 | chart_teamBurndown[team]['closedTicketsData'] << "\"#{teamBurndown[team]['closed'].to_s}\","
54 | end
55 | weekOf = endTime
56 | end
57 |
58 | chart_labels << "]"
59 | chart_openTicketsData << "]"
60 | chart_closedTicketsData << "]"
61 | teamGroups.each do |team|
62 | chart_teamBurndown[team]['openTicketsData'] << "]"
63 | chart_teamBurndown[team]['closedTicketsData'] << "]"
64 | end
65 |
66 | %>
67 |
68 |
69 |
120 |
121 | <% teamGroups.each do |team| %>
122 |
123 |
174 | <% end %>
175 |
--------------------------------------------------------------------------------
/app/views/reports/sla.html.erb:
--------------------------------------------------------------------------------
1 | sla.html.erb is here!
2 |
--------------------------------------------------------------------------------
/app/views/settings/_report_settings.html.erb:
--------------------------------------------------------------------------------
1 | this is config
2 |
--------------------------------------------------------------------------------
/assets/images/reports.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dchbx/redmine_reports/a44d4afca1f9695d8194f2ec11a195adce7b8616/assets/images/reports.png
--------------------------------------------------------------------------------
/config/locales/en.yml:
--------------------------------------------------------------------------------
1 | # English strings go here for Rails i18n
2 | en:
3 | # my_label: "My label"
4 |
--------------------------------------------------------------------------------
/config/routes.rb:
--------------------------------------------------------------------------------
1 | # Plugin's routes
2 | # See: http://guides.rubyonrails.org/routing.html
3 |
4 | get 'reports', :to => 'dchbxreports#index'
5 | get 'reports/sla', :to => 'dchbxreports#sla'
6 | get 'reports/holdup', :to => 'dchbxreports#userHoldUp'
7 | get 'reports/status', :to => 'dchbxreports#status'
8 | #get 'reports/stakeholders', :to => 'dchbxreports#stakeholders'
9 | get 'reports/duedates', :to => 'dchbxreports#duedates'
10 | get 'reports/usersReturnForDef', :to => 'dchbxreports#usersReturnForDef'
11 | get 'reports/velocity', :to => 'dchbxreports#velocity'
12 |
--------------------------------------------------------------------------------
/init.rb:
--------------------------------------------------------------------------------
1 | Redmine::Plugin.register :redmine_reports do
2 | name 'Redmine Reports plugin'
3 | author 'IdeaCrew, Inc'
4 | description ''
5 | version '0.0.1'
6 | url 'https://github.com/dchbx/redmine_reports'
7 | author_url 'http://ideacrew.com'
8 | menu :top_menu, :reports, { :controller => 'dchbxreports', :action => 'index' }, :caption => 'Reports'
9 | settings :default => {
10 | 'slaShowProgressTime' => 7*24*60*60,
11 | 'slas' => [
12 | {
13 | 'type' => 'trackers',
14 | 'id' => '22',
15 | 'timeToResolve' => 2*24*60*60,
16 | 'sinceCreation' => 'true'
17 | },
18 | {
19 | 'type' => 'enumerations',
20 | 'id' => '16',
21 | 'timeToResolve' => 2*24*60*60,
22 | 'sinceCreation' => 'true'
23 | },
24 | {
25 | 'type' => 'enumerations',
26 | 'id' => '17',
27 | 'timeToResolve' => 5*24*60*60,
28 | 'sinceCreation' => 'true'
29 | },
30 | {
31 | 'type' => 'enumerations',
32 | 'id' => '18',
33 | 'timeToResolve' => 10*24*60*60,
34 | 'sinceCreation' => 'true'
35 | },
36 | {
37 | 'type' => 'enumerations',
38 | 'id' => '19',
39 | 'timeToResolve' => 30*24*60*60,
40 | 'sinceCreation' => 'true'
41 | },
42 | {
43 | 'type' => 'enumerations',
44 | 'id' => '20',
45 | 'timeToResolve' => 90*24*60*60,
46 | 'sinceCreation' => 'true'
47 | },
48 | {
49 | 'type' => 'issue_status',
50 | 'id' => '28',
51 | 'timeToResolve' => 7*24*60*60,
52 | 'sinceCreation' => 'false'
53 | },
54 | {
55 | 'type' => 'issue_status',
56 | 'id' => '9',
57 | 'timeToResolve' => 7*24*60*60,
58 | 'sinceCreation' => 'false'
59 | },
60 | {
61 | 'type' => 'issue_status',
62 | 'id' => '6',
63 | 'timeToResolve' => 7*24*60*60,
64 | 'sinceCreation' => 'false'
65 | },
66 | {
67 | 'type' => 'issue_status',
68 | 'id' => '29',
69 | 'timeToResolve' => 7*24*60*60,
70 | 'sinceCreation' => 'false'
71 | },
72 | ]
73 | }, :partial => 'settings/report_settings'
74 | end
75 |
--------------------------------------------------------------------------------
/test/functional/dchbxreports_controller_test.rb:
--------------------------------------------------------------------------------
1 | require File.expand_path('../../test_helper', __FILE__)
2 |
3 | class DchbxreportsControllerTest < ActionController::TestCase
4 | # Replace this with your real tests.
5 | def test_truth
6 | assert true
7 | end
8 | end
9 |
--------------------------------------------------------------------------------
/test/functional/reports_controller_test.rb:
--------------------------------------------------------------------------------
1 | require File.expand_path('../../test_helper', __FILE__)
2 |
3 | class ReportsControllerTest < ActionController::TestCase
4 | # Replace this with your real tests.
5 | def test_truth
6 | assert true
7 | end
8 | end
9 |
--------------------------------------------------------------------------------
/test/test_helper.rb:
--------------------------------------------------------------------------------
1 | # Load the Redmine helper
2 | require File.expand_path(File.dirname(__FILE__) + '/../../../test/test_helper')
3 |
--------------------------------------------------------------------------------