Commit b9d345d2 by Tấn Trần Thanh

fix bug and add a field user ids

parent 94a13e5c
Pipeline #1592 canceled with stages
in 0 seconds
...@@ -5,3 +5,4 @@ gem 'faraday', '~> 0.17.6' ...@@ -5,3 +5,4 @@ gem 'faraday', '~> 0.17.6'
gem 'hashie', '~> 3.5', '>= 3.5.7' gem 'hashie', '~> 3.5', '>= 3.5.7'
gem 'oauth2', '~> 1.2' gem 'oauth2', '~> 1.2'
gem 'github_api', '~> 0.19.0' gem 'github_api', '~> 0.19.0'
gem 'slim', '~> 4.1'
...@@ -13,19 +13,29 @@ class WorkflowReportController < ApplicationController ...@@ -13,19 +13,29 @@ class WorkflowReportController < ApplicationController
def show_daily_report def show_daily_report
date = params[:date].split('-') date = params[:date].split('-')
result = []
report = {}
if params[:user_ids].blank?
project_id = Project.find_by(name: params[:team]).id project_id = Project.find_by(name: params[:team]).id
project_ids = Project.visible.active.where(parent_id: project_id).pluck(:id).push(project_id) project_ids = Project.visible.active.where(parent_id: project_id).pluck(:id).push(project_id)
users_by_role = Project.find(project_id).users_by_role users_by_role = Project.find(project_id).users_by_role
result = []
users_by_role.each do |role, users| users_by_role.each do |role, users|
users.each do |u| users.each do |u|
result << { id: u.id, fullname: "#{u.firstname} #{u.lastname}" } unless role.name.in?(%w[Manager JP TeamLead]) result << { id: u.id, fullname: "#{u.firstname} #{u.lastname}" } unless role.name.in?(%w[Manager JP TeamLead])
end end
end end
report = {}
result.each do |user| result.each do |user|
report[user[:fullname]] = WorkflowReportTimeEntries.query_time_entry(user[:id], date[0].to_i, date[1].to_i, date[2].to_i, project_ids) report[user[:fullname]] = WorkflowReportTimeEntries.query_time_entry(user[:id], date[0].to_i, date[1].to_i, date[2].to_i, project_ids)
end end
else
user_ids = params[:user_ids].gsub(/[^0-9,]/, '').split(',')
users = User.where(id: user_ids)
cookies[:daily_report] = { value: "#{user_ids.join(',')}", expires: 90.days.from_now } if cookies[:daily_report] != user_ids.join(',')
users.each do |u|
report["#{u.firstname} #{u.lastname}"] = WorkflowReportTimeEntries.query_time_entry_without_project(u.id, date[0].to_i, date[1].to_i, date[2].to_i)
end
end
respond_to do |format| respond_to do |format|
format.js { render 'build_report', locals: { report: report, display_hour: params[:display_hour] } } format.js { render 'build_report', locals: { report: report, display_hour: params[:display_hour] } }
...@@ -35,8 +45,9 @@ class WorkflowReportController < ApplicationController ...@@ -35,8 +45,9 @@ class WorkflowReportController < ApplicationController
def export def export
team = params[:team] team = params[:team]
project_ids = $workflow_report_config['teams'].select { |hash| hash.key?(team) }[0][team] project_ids = $workflow_report_config['teams'].select { |hash| hash.key?(team) }[0][team]
result = WorkflowReport.build_report(params[:year].to_i, params[:month].to_i, project_ids) result = Rails.cache.fetch("#{team}_#{params[:year]}_#{params[:month]}", expires_in: 1.hours) do
WorkflowReport.build_report(params[:year].to_i, params[:month].to_i, project_ids)
end
respond_to do |format| respond_to do |format|
format.js { render 'build_table', locals: { result: result, thead: TABLE_HEADER } } format.js { render 'build_table', locals: { result: result, thead: TABLE_HEADER } }
end end
......
...@@ -3,7 +3,15 @@ class WorkflowReportTimeEntries < TimeEntry ...@@ -3,7 +3,15 @@ class WorkflowReportTimeEntries < TimeEntry
scope :query_time_entry, ->(user_id, year, month, day, project_ids) { scope :query_time_entry, ->(user_id, year, month, day, project_ids) {
where("#{TimeEntry.table_name}.user_id = ? AND #{TimeEntry.table_name}.spent_on BETWEEN ? AND ?", user_id, DateTime.new(year, month, day).beginning_of_day - JP_TIME_ZONE.hours, DateTime.new(year, month, day).end_of_day - JP_TIME_ZONE.hours). where("#{TimeEntry.table_name}.user_id = ? AND #{TimeEntry.table_name}.spent_on BETWEEN ? AND ?", user_id, DateTime.new(year, month, day).beginning_of_day - JP_TIME_ZONE.hours, DateTime.new(year, month, day).end_of_day - JP_TIME_ZONE.hours).
where(projects: {id: project_ids}). where(projects: { id: project_ids }).
joins(:activity, :project).
references(:issue => [:tracker, :status]).
includes(:issue => [:tracker, :status, :assigned_to, :priority]).
order("#{TimeEntry.table_name}.spent_on DESC, #{Project.table_name}.name ASC, #{Tracker.table_name}.position ASC, #{Issue.table_name}.id ASC")
}
scope :query_time_entry_without_project, ->(user_id, year, month, day) {
where("#{TimeEntry.table_name}.user_id = ? AND #{TimeEntry.table_name}.spent_on BETWEEN ? AND ?", user_id, DateTime.new(year, month, day).beginning_of_day - JP_TIME_ZONE.hours, DateTime.new(year, month, day).end_of_day - JP_TIME_ZONE.hours).
joins(:activity, :project). joins(:activity, :project).
references(:issue => [:tracker, :status]). references(:issue => [:tracker, :status]).
includes(:issue => [:tracker, :status, :assigned_to, :priority]). includes(:issue => [:tracker, :status, :assigned_to, :priority]).
......
= stylesheet_link_tag 'style', plugin: 'workflow_report' = stylesheet_link_tag 'style', plugin: 'workflow_report'
= javascript_include_tag(:application, :plugin => 'workflow_report') = javascript_include_tag(:application, :plugin => 'workflow_report')
- user_ids = cookies[:daily_report] || ''
= content_for :sidebar do = content_for :sidebar do
= render 'side_content' = render 'side_content'
...@@ -10,12 +11,16 @@ fieldset.box.tabular ...@@ -10,12 +11,16 @@ fieldset.box.tabular
= form_tag workflow_report_daily_export_path, method: :get, remote: true, id: 'export-form' do = form_tag workflow_report_daily_export_path, method: :get, remote: true, id: 'export-form' do
p p
= label :team, 'Team' = label :team, 'Team'
= select_tag :team, options_for_select(@team_options), { prompt: "Select team" } = select_tag :team, options_for_select(@team_options), { prompt: 'Select team', disabled: ('true' unless user_ids.blank?) }
p p
= label :team, 'Date' = label :team, 'Date'
= date_field_tag :date, Date.current = date_field_tag :date, Date.current
p p
= label :userIdCheckbox, 'With User IDs'
= text_field_tag :user_ids, user_ids, disabled: ('true' if user_ids.blank?), placeholder: 'Ex: 123,124,125'
= check_box_tag :userIdCheckbox, '0', user_ids.blank? ? false : true
p
= label :display_hour, 'Display hour' = label :display_hour, 'Display hour'
= check_box_tag :display_hour, '1', true = check_box_tag :display_hour, '1', true
= submit_tag 'export', id: 'export' = submit_tag 'SHOW DAILY', id: 'export'
#daily_report #daily_report
window.addEventListener('load', function () { window.addEventListener('load', function () {
$('#userIdCheckbox').change(function () {
const isChecked = $(this).is(':checked');
$('#team').prop('disabled', isChecked).val('');
$('#user_ids').prop('disabled', !isChecked);
})
$('#export-form').submit(function () { $('#export-form').submit(function () {
let checkTeamAndUsers
const month = $('#month').val() const month = $('#month').val()
const year = $('#year').val() const year = $('#year').val()
const team = $('#team').val() const team = $('#team').val()
const userIds = $('#userIdCheckbox').is(':checked') ? $('#user_ids').val() : undefined
if (month === '' || year === '' || team === '') { if (userIds === undefined) {
checkTeamAndUsers = team === ''
} else {
checkTeamAndUsers = team === '' && userIds === ''
}
if (month === '' || year === '' || checkTeamAndUsers) {
alert('Please complete all the necessary fields.') alert('Please complete all the necessary fields.')
return false return false
} }
...@@ -22,25 +36,25 @@ window.addEventListener('load', function () { ...@@ -22,25 +36,25 @@ window.addEventListener('load', function () {
aTag.click() aTag.click()
} }
$(".export-button").on("click", function () { $('.export-button').on('click', function () {
exportToCSV() exportToCSV()
}) })
function exportToCSV() { function exportToCSV() {
const table = $("table") const table = $('table')
const rows = table.find("tr") const rows = table.find('tr')
let csv = [] let csv = []
rows.each(function (index) { rows.each(function (index) {
const cols = $(this).find("td, th") const cols = $(this).find('td, th')
let rowText = [] let rowText = []
let currentColspan = 1 let currentColspan = 1
cols.each(function () { cols.each(function () {
const text_report = $(this).text() const text_report = $(this).text()
if ($(this).attr("colspan")) { if ($(this).attr('colspan')) {
currentColspan = parseInt($(this).attr("colspan"), 10) currentColspan = parseInt($(this).attr('colspan'), 10)
} }
if (currentColspan > 1) { if (currentColspan > 1) {
...@@ -48,14 +62,18 @@ window.addEventListener('load', function () { ...@@ -48,14 +62,18 @@ window.addEventListener('load', function () {
i === 0 ? rowText.push(text_report) : rowText.push('') i === 0 ? rowText.push(text_report) : rowText.push('')
} }
} else { } else {
text_report.includes(',') ? rowText.push(`"${text_report}"`) : rowText.push(text_report) if (text_report.includes(',') || text_report.includes('\n')) {
rowText.push(`"${text_report}"`);
} else {
rowText.push(text_report);
}
} }
currentColspan = Math.max(1, currentColspan - 1) currentColspan = Math.max(1, currentColspan - 1)
}); });
csv.push(rowText.join(",")) csv.push(rowText.join(','))
}); });
const csvContent = csv.join("\n") const csvContent = csv.join('\n')
download(csvContent) download(csvContent)
} }
}) })
...@@ -73,3 +73,7 @@ button.export-button { ...@@ -73,3 +73,7 @@ button.export-button {
.text-center { .text-center {
text-align: center; text-align: center;
} }
#user_ids {
margin-right: 8px;
}
...@@ -4,6 +4,9 @@ module WorkflowReport ...@@ -4,6 +4,9 @@ module WorkflowReport
'4. Testing', '5. Bug fixing', '6. Release', 'Others', 'testcases', 'vn STG bug', 'Jp STG bug', 'Production', 'Issue', 'Issue comment', 'PR comment', 'Review comment', 'Commits', 'File changed', 'Addtion', 'Deletetion'] '4. Testing', '5. Bug fixing', '6. Release', 'Others', 'testcases', 'vn STG bug', 'Jp STG bug', 'Production', 'Issue', 'Issue comment', 'PR comment', 'Review comment', 'Commits', 'File changed', 'Addtion', 'Deletetion']
EST_DETAIL_FIRST_COL = 14 EST_DETAIL_FIRST_COL = 14
ACTUAL_TIME_DETAIL_FIRST_COL = 21 ACTUAL_TIME_DETAIL_FIRST_COL = 21
PR_CMT_COL = 34
PROCESS = ['1. Requirement', '2. Design', '3. Coding', '4. Testing', '5. Bug fixing', '6. Release', '']
BUGS = { testcases: 28, bugs: 29, stg_bugs: 30, prod_bugs: 31 }
class << self class << self
def build_report(year, month, project_ids) def build_report(year, month, project_ids)
...@@ -67,48 +70,29 @@ module WorkflowReport ...@@ -67,48 +70,29 @@ module WorkflowReport
end end
process = get_process(issue.subject.gsub(/[^[:print:]]/, '')) process = get_process(issue.subject.gsub(/[^[:print:]]/, ''))
case process if PROCESS.include?(process)
when '1. Requirement' PROCESS.each_with_index do |proc, index|
result[EST_DETAIL_FIRST_COL].push(issue.estimated_hours.present? ? issue.estimated_hours : '') if proc == process
result[ACTUAL_TIME_DETAIL_FIRST_COL].push(issue.spent_hours.positive? ? issue.spent_hours : '') build_est_to_actual_time!(result, EST_DETAIL_FIRST_COL, issue.estimated_hours.to_f, index)
when '2. Design' build_est_to_actual_time!(result, ACTUAL_TIME_DETAIL_FIRST_COL, issue.spent_hours.to_f, index)
result[EST_DETAIL_FIRST_COL + 1].push(issue.estimated_hours.present? ? issue.estimated_hours : '')
result[ACTUAL_TIME_DETAIL_FIRST_COL + 1].push(issue.spent_hours.positive? ? issue.spent_hours : '')
when '3. Coding'
result[EST_DETAIL_FIRST_COL + 2].push(issue.estimated_hours.present? ? issue.estimated_hours : '')
result[ACTUAL_TIME_DETAIL_FIRST_COL + 2].push(issue.spent_hours.positive? ? issue.spent_hours : '')
when '4. Testing'
result[EST_DETAIL_FIRST_COL + 3].push(issue.estimated_hours.present? ? issue.estimated_hours : '')
result[ACTUAL_TIME_DETAIL_FIRST_COL + 3].push(issue.spent_hours.positive? ? issue.spent_hours : '')
when '5. Bug fixing'
result[EST_DETAIL_FIRST_COL + 4].push(issue.estimated_hours.present? ? issue.estimated_hours : '')
result[ACTUAL_TIME_DETAIL_FIRST_COL + 4].push(issue.spent_hours.positive? ? issue.spent_hours : '')
when '6. Release'
result[EST_DETAIL_FIRST_COL + 5].push(issue.estimated_hours.present? ? issue.estimated_hours : '')
result[ACTUAL_TIME_DETAIL_FIRST_COL + 5].push(issue.spent_hours.positive? ? issue.spent_hours : '')
else else
result[EST_DETAIL_FIRST_COL + 6].push(issue.estimated_hours.present? ? issue.estimated_hours : '') result[EST_DETAIL_FIRST_COL + index].push(0) if result[EST_DETAIL_FIRST_COL + index][result[0].length - 1].nil?
result[ACTUAL_TIME_DETAIL_FIRST_COL + 6].push(issue.spent_hours.positive? ? issue.spent_hours : '') result[ACTUAL_TIME_DETAIL_FIRST_COL + index].push(0) if result[ACTUAL_TIME_DETAIL_FIRST_COL + index][result[0].length - 1].nil?
end
end
else
build_est_to_actual_time!(result, EST_DETAIL_FIRST_COL, issue.estimated_hours.to_f, 6)
build_est_to_actual_time!(result, ACTUAL_TIME_DETAIL_FIRST_COL, issue.spent_hours.to_f, 6)
end end
end end
if sum_hours_record.nil? if sum_hours_record.nil?
# testcases # testcases, internal bug, stg bug, prod bug
result[28] << '' (28..31).each { |i| result[i] << '' }
# internal bug
result[29] << ''
# stg bug
result[30] << ''
# prod bug
result[31] << ''
else else
# testcases # testcases, internal bug, stg bug, prod bug
result[28] << sum_hours_record[:testcases] if sum_hours_record[:testcases].to_i >= 0 BUGS.each do |status, column|
# internal bug result[column].push(sum_hours_record[status].to_i >= 0 ? sum_hours_record[status] : '')
result[29] << sum_hours_record[:bugs] if sum_hours_record[:bugs].to_i >= 0 end
# stg bug
result[30] << sum_hours_record[:stg_bugs] if sum_hours_record[:stg_bugs].to_i >= 0
# prod bug
result[31] << sum_hours_record[:prod_bugs] if sum_hours_record[:prod_bugs].to_i >= 0
end end
if jp_request.present? if jp_request.present?
jp_request = jp_request.strip jp_request = jp_request.strip
...@@ -127,37 +111,27 @@ module WorkflowReport ...@@ -127,37 +111,27 @@ module WorkflowReport
result[33] << '' result[33] << ''
end end
# pr detail # pr detail
next unless pull_request.present? pr = { pr_comments: 0, pr_review_comments: 0, pr_commits: 0, pr_additions: 0, pr_deletions: 0, pr_changed_files: 0 }
pr_comments = 0
pr_review_comments = 0
pr_commits = 0
pr_additions = 0
pr_deletions = 0
pr_changed_files = 0
prs = pull_request.split("\r\n").compact
if pull_request.present?
prs = pull_request.split("\r\n").compact
prs.each do |link| prs.each do |link|
pr_link_arr = URI(link.strip).path.split('/').compact_blank pr_link_arr = URI(link.strip).path.split('/').reject!(&:empty?)
next unless pr_link_arr.length == 4 next unless pr_link_arr.length == 4
begin
pr_detail = github.pull_requests.find user: pr_link_arr[0], repo: pr_link_arr[1], number: pr_link_arr[3] pr_detail = github.pull_requests.find user: pr_link_arr[0], repo: pr_link_arr[1], number: pr_link_arr[3]
if pr_detail.success? if pr_detail.success?
pr_comments += pr_detail.comments pr[:pr_comments] += pr_detail.comments
pr_review_comments += pr_detail.review_comments pr[:pr_review_comments] += pr_detail.review_comments
pr_commits += pr_detail.commits pr[:pr_commits] += pr_detail.commits
pr_additions += pr_detail.additions pr[:pr_additions] += pr_detail.additions
pr_deletions += pr_detail.deletions pr[:pr_deletions] += pr_detail.deletions
pr_changed_files += pr_detail.changed_files pr[:pr_changed_files] += pr_detail.changed_files
end end
end end
end
result[34] << pr_comments pr.each_with_index do |(key, _detail), index|
result[35] << pr_review_comments result[PR_CMT_COL + index] << pr[key]
result[36] << pr_commits
result[37] << pr_changed_files
result[38] << pr_additions
result[39] << pr_deletions
end end
end end
...@@ -196,7 +170,16 @@ module WorkflowReport ...@@ -196,7 +170,16 @@ module WorkflowReport
end end
end end
end end
name.strip name.strip
end end
def build_est_to_actual_time!(result, column, time, index)
if result[column + index][result[0].length - 1].present?
result[column + index][result[0].length - 1] = result[column + index][result[0].length - 1] + time
else
result[column + index].push(time)
end
end
end end
end end
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment