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'
gem 'hashie', '~> 3.5', '>= 3.5.7'
gem 'oauth2', '~> 1.2'
gem 'github_api', '~> 0.19.0'
gem 'slim', '~> 4.1'
......@@ -13,19 +13,29 @@ class WorkflowReportController < ApplicationController
def show_daily_report
date = params[:date].split('-')
result = []
report = {}
if params[:user_ids].blank?
project_id = Project.find_by(name: params[:team]).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
result = []
users_by_role.each do |role, users|
users.each do |u|
result << { id: u.id, fullname: "#{u.firstname} #{u.lastname}" } unless role.name.in?(%w[Manager JP TeamLead])
end
end
report = {}
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)
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|
format.js { render 'build_report', locals: { report: report, display_hour: params[:display_hour] } }
......@@ -35,8 +45,9 @@ class WorkflowReportController < ApplicationController
def export
team = params[: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|
format.js { render 'build_table', locals: { result: result, thead: TABLE_HEADER } }
end
......
......@@ -3,7 +3,15 @@ class WorkflowReportTimeEntries < TimeEntry
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(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).
references(:issue => [:tracker, :status]).
includes(:issue => [:tracker, :status, :assigned_to, :priority]).
......
= stylesheet_link_tag 'style', plugin: 'workflow_report'
= javascript_include_tag(:application, :plugin => 'workflow_report')
- user_ids = cookies[:daily_report] || ''
= content_for :sidebar do
= render 'side_content'
......@@ -10,12 +11,16 @@ fieldset.box.tabular
= form_tag workflow_report_daily_export_path, method: :get, remote: true, id: 'export-form' do
p
= 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
= label :team, 'Date'
= date_field_tag :date, Date.current
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'
= check_box_tag :display_hour, '1', true
= submit_tag 'export', id: 'export'
= submit_tag 'SHOW DAILY', id: 'export'
#daily_report
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 () {
let checkTeamAndUsers
const month = $('#month').val()
const year = $('#year').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.')
return false
}
......@@ -22,25 +36,25 @@ window.addEventListener('load', function () {
aTag.click()
}
$(".export-button").on("click", function () {
$('.export-button').on('click', function () {
exportToCSV()
})
function exportToCSV() {
const table = $("table")
const rows = table.find("tr")
const table = $('table')
const rows = table.find('tr')
let csv = []
rows.each(function (index) {
const cols = $(this).find("td, th")
const cols = $(this).find('td, th')
let rowText = []
let currentColspan = 1
cols.each(function () {
const text_report = $(this).text()
if ($(this).attr("colspan")) {
currentColspan = parseInt($(this).attr("colspan"), 10)
if ($(this).attr('colspan')) {
currentColspan = parseInt($(this).attr('colspan'), 10)
}
if (currentColspan > 1) {
......@@ -48,14 +62,18 @@ window.addEventListener('load', function () {
i === 0 ? rowText.push(text_report) : rowText.push('')
}
} 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)
});
csv.push(rowText.join(","))
csv.push(rowText.join(','))
});
const csvContent = csv.join("\n")
const csvContent = csv.join('\n')
download(csvContent)
}
})
......@@ -73,3 +73,7 @@ button.export-button {
.text-center {
text-align: center;
}
#user_ids {
margin-right: 8px;
}
......@@ -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']
EST_DETAIL_FIRST_COL = 14
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
def build_report(year, month, project_ids)
......@@ -67,48 +70,29 @@ module WorkflowReport
end
process = get_process(issue.subject.gsub(/[^[:print:]]/, ''))
case process
when '1. Requirement'
result[EST_DETAIL_FIRST_COL].push(issue.estimated_hours.present? ? issue.estimated_hours : '')
result[ACTUAL_TIME_DETAIL_FIRST_COL].push(issue.spent_hours.positive? ? issue.spent_hours : '')
when '2. Design'
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 : '')
if PROCESS.include?(process)
PROCESS.each_with_index do |proc, index|
if proc == process
build_est_to_actual_time!(result, EST_DETAIL_FIRST_COL, issue.estimated_hours.to_f, index)
build_est_to_actual_time!(result, ACTUAL_TIME_DETAIL_FIRST_COL, issue.spent_hours.to_f, index)
else
result[EST_DETAIL_FIRST_COL + 6].push(issue.estimated_hours.present? ? issue.estimated_hours : '')
result[ACTUAL_TIME_DETAIL_FIRST_COL + 6].push(issue.spent_hours.positive? ? issue.spent_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 + 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
if sum_hours_record.nil?
# testcases
result[28] << ''
# internal bug
result[29] << ''
# stg bug
result[30] << ''
# prod bug
result[31] << ''
# testcases, internal bug, stg bug, prod bug
(28..31).each { |i| result[i] << '' }
else
# testcases
result[28] << sum_hours_record[:testcases] if sum_hours_record[:testcases].to_i >= 0
# internal bug
result[29] << sum_hours_record[:bugs] if sum_hours_record[:bugs].to_i >= 0
# 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
# testcases, internal bug, stg bug, prod bug
BUGS.each do |status, column|
result[column].push(sum_hours_record[status].to_i >= 0 ? sum_hours_record[status] : '')
end
end
if jp_request.present?
jp_request = jp_request.strip
......@@ -127,37 +111,27 @@ module WorkflowReport
result[33] << ''
end
# pr detail
next unless pull_request.present?
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
pr = { pr_comments: 0, pr_review_comments: 0, pr_commits: 0, pr_additions: 0, pr_deletions: 0, pr_changed_files: 0 }
if pull_request.present?
prs = pull_request.split("\r\n").compact
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
begin
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?
pr_comments += pr_detail.comments
pr_review_comments += pr_detail.review_comments
pr_commits += pr_detail.commits
pr_additions += pr_detail.additions
pr_deletions += pr_detail.deletions
pr_changed_files += pr_detail.changed_files
pr[:pr_comments] += pr_detail.comments
pr[:pr_review_comments] += pr_detail.review_comments
pr[:pr_commits] += pr_detail.commits
pr[:pr_additions] += pr_detail.additions
pr[:pr_deletions] += pr_detail.deletions
pr[:pr_changed_files] += pr_detail.changed_files
end
end
result[34] << pr_comments
result[35] << pr_review_comments
result[36] << pr_commits
result[37] << pr_changed_files
result[38] << pr_additions
result[39] << pr_deletions
end
pr.each_with_index do |(key, _detail), index|
result[PR_CMT_COL + index] << pr[key]
end
end
......@@ -196,7 +170,16 @@ module WorkflowReport
end
end
end
name.strip
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
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