Commit b77fc250 by Tấn Trần Thanh

done for build time report and download csv

parent 9d0bc2a6
Pipeline #1617 failed with stages
in 0 seconds
...@@ -44,11 +44,7 @@ class WorkflowReportController < ApplicationController ...@@ -44,11 +44,7 @@ class WorkflowReportController < ApplicationController
def export def export
team = params[:team] team = params[:team]
project_ids = if team == 'All-team' project_ids = find_project_ids(team)
$workflow_report_config['teams'].map(&:values).flatten.compact
else
$workflow_report_config['teams'].find { |hash| hash.key?(team) }[team]
end
result = Rails.cache.fetch("#{team}_#{params[:year]}_#{params[:month]}", expires_in: team == 'All-team' ? 1.hours : 1.days) do result = Rails.cache.fetch("#{team}_#{params[:year]}_#{params[:month]}", expires_in: team == 'All-team' ? 1.hours : 1.days) do
WorkflowReport.build_report(params[:year].to_i, params[:month].to_i, project_ids) WorkflowReport.build_report(params[:year].to_i, params[:month].to_i, project_ids)
...@@ -59,9 +55,31 @@ class WorkflowReportController < ApplicationController ...@@ -59,9 +55,31 @@ class WorkflowReportController < ApplicationController
end end
end end
def index_time_entry
@team_options = $workflow_report_config['teams'].map { |team| team.keys() }
end
def export_time_entry
team = params[:team]
project_ids = find_project_ids(team)
result = WorkflowReport.build_time_entry_report(project_ids, params[:date_from], params[:date_to])
respond_to do |format|
format.js { render 'build_table_time_entry', locals: { result: result, thead: TIME_ENTRY_HEADER } }
end
end
private private
def require_xhr_request def require_xhr_request
head :unprocessable_entity unless request.xhr? head :unprocessable_entity unless request.xhr?
end end
def find_project_ids(team)
if team == 'All-team'
$workflow_report_config['teams'].map(&:values).flatten.compact
else
$workflow_report_config['teams'].find { |hash| hash.key?(team) }[team]
end
end
end end
...@@ -12,4 +12,12 @@ class WorkflowReportIssue < Issue ...@@ -12,4 +12,12 @@ class WorkflowReportIssue < Issue
year, month, DateTime.new(year, month).beginning_of_day, DateTime.new(year, month, -1).end_of_day]) year, month, DateTime.new(year, month).beginning_of_day, DateTime.new(year, month, -1).end_of_day])
.order(Arel.sql("FIELD(projects.id, #{project_ids.join(',')})"), :root_id) .order(Arel.sql("FIELD(projects.id, #{project_ids.join(',')})"), :root_id)
} }
scope :raw_task_in_date, -> (date_from, date_to, project_ids) {
includes(:project, :time_entries)
.where('time_entries.spent_on BETWEEN ? AND ?', date_from, date_to)
.where(projects: { id: project_ids })
.group('issues.root_id')
.order('projects.name', :root_id)
}
end end
...@@ -2,3 +2,4 @@ h3 Report ...@@ -2,3 +2,4 @@ h3 Report
ul ul
li = link_to 'Workflow Report', workflow_report_path li = link_to 'Workflow Report', workflow_report_path
li = link_to 'Daily Report', workflow_report_daily_path li = link_to 'Daily Report', workflow_report_daily_path
li = link_to 'Time Entry Report', workflow_report_time_entry_path
- grand_total = result.last&.compact&.sum
h2 = "Total: #{result[0]&.length}"
- if result.present?
table.h-fit[border="1"]
tr.purple
th = "Grand Total (hours): #{grand_total.round(2)}"
th = "Grand Total (days): #{(grand_total / 8).round(2)}"
table[border="1"]
tr.header_table--visible
th.green[colspan="5"] Div Report
tr.header_table--visible.none_colspan
- thead.each_with_index do |head, index|
th.yellow = head
- result[0].each_with_index do |root_id, index|
tr
- (0..(thead.length - 1)).each do |i|
td = result[i][index]
- else
h1.text-center There is no data for the 'time entry report' table.
$("#data_workflow").html("<%= escape_javascript(render partial: 'table_time_entry', locals: { result: result,thead: thead } ) %>")
<% if result.present? %>
$('button.export-button').removeClass('d-none')
<% else %>
$('button.export-button').addClass('d-none')
<% end %>
= stylesheet_link_tag 'style', plugin: 'workflow_report'
= javascript_include_tag(:application, :plugin => 'workflow_report')
= content_for :sidebar do
= render 'side_content'
fieldset.box.tabular
legend
| EXPORT TIME ENTRY REPORT
= form_tag workflow_report_time_entry_export_path, method: :get, remote: true, id: 'export-form' do
p
= label :date_from, 'Date from'
= date_field_tag :date_from, Date.today - 7.days
p
= label :date_from, 'Date to'
= date_field_tag :date_to, Date.today
p
= label :team, 'Team'
= select_tag :team, options_for_select(@team_options), { prompt: "Select team" }
= submit_tag 'FIND', id: 'export'
button.export-button.d-none Download .CSV
#data_workflow
...@@ -32,7 +32,11 @@ window.addEventListener('load', function () { ...@@ -32,7 +32,11 @@ window.addEventListener('load', function () {
const aTag = document.createElement('a') const aTag = document.createElement('a')
const fileName = $('#year').val() + $('#month').val() + $('#team').val() const fileName = $('#year').val() + $('#month').val() + $('#team').val()
aTag.setAttribute('href', url) aTag.setAttribute('href', url)
aTag.setAttribute('download', `${$('#year').val()}-${$('#month').val()}-${$('#team').val()}.csv`) if ($('#date_from').val()) {
aTag.setAttribute('download', `${$('#date_from').val()}-${$('#date_to').val()}-${$('#team').val()}.csv`)
} else {
aTag.setAttribute('download', `${$('#year').val()}-${$('#month').val()}-${$('#team').val()}.csv`)
}
aTag.click() aTag.click()
} }
......
#data_workflow > table, #data_workflow > h1 { #data_workflow > table, #data_workflow > h1 {
width: 100%; max-width: 100%;
overflow: auto; overflow: auto;
height: 100vh; height: 100vh;
} }
...@@ -149,3 +149,7 @@ td.notes { ...@@ -149,3 +149,7 @@ td.notes {
.w-100 { .w-100 {
width: 100%; width: 100%;
} }
.h-fit {
height: fit-content !important;
}
...@@ -5,3 +5,5 @@ get 'workflow_report', to: 'workflow_report#index' ...@@ -5,3 +5,5 @@ get 'workflow_report', to: 'workflow_report#index'
get 'workflow_report/export', to: 'workflow_report#export' get 'workflow_report/export', to: 'workflow_report#export'
get 'workflow_report/daily', to: 'workflow_report#index_daily_report' get 'workflow_report/daily', to: 'workflow_report#index_daily_report'
get 'workflow_report/daily/export', to: 'workflow_report#show_daily_report' get 'workflow_report/daily/export', to: 'workflow_report#show_daily_report'
get 'workflow_report/time_entry', to: 'workflow_report#index_time_entry'
get 'workflow_report/time_entry/export', to: 'workflow_report#export_time_entry'
...@@ -2,6 +2,7 @@ module WorkflowReport ...@@ -2,6 +2,7 @@ module WorkflowReport
TABLE_HEADER = ['root_id', 'project', 'subject', 'target_version', 'created_on ', 'closed_on ', 'due_date ', 'status ', 'Estimated_hours (*final version)', 'Actual time', 'Diff', 'Estimated_hours (*Initial version)', TABLE_HEADER = ['root_id', 'project', 'subject', 'target_version', 'created_on ', 'closed_on ', 'due_date ', 'status ', 'Estimated_hours (*final version)', 'Actual time', 'Diff', 'Estimated_hours (*Initial version)',
'Number of estimation changes', 'Note of estimation changes', '1. Requirement', '2. Design', '3. Coding', '4. Testing', '5. Bug fixing', '6. Release', 'Others', '1. Requirement', '2. Design', '3. Coding', 'Number of estimation changes', 'Note of estimation changes', '1. Requirement', '2. Design', '3. Coding', '4. Testing', '5. Bug fixing', '6. Release', 'Others', '1. Requirement', '2. Design', '3. Coding',
'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'].freeze '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'].freeze
TIME_ENTRY_HEADER = ['Site', 'Title', 'JP Request', 'Grand Total']
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 PR_CMT_COL = 34
...@@ -32,13 +33,13 @@ module WorkflowReport ...@@ -32,13 +33,13 @@ module WorkflowReport
result[0] << root_id result[0] << root_id
result[1] << issues.first.project.name.gsub(/[^[:print:]]/, '') result[1] << issues.first.project.name.gsub(/[^[:print:]]/, '')
result[2] << root_issue&.subject.gsub(/[^[:print:]]/, '') result[2] << root_issue&.subject.gsub(/[^[:print:]]/, '')
result[3] << issues.first.workflow_report_version&.name result[3] << root_issue.workflow_report_version&.name
issue_created_on = issues.min_by { |i| i[:created_on] if i[:created_on].present? } issue_created_on = arr_issue.min_by { |i| i[:created_on] if i[:created_on].present? }
result[4].push(issue_created_on.present? ? issue_created_on.created_on&.strftime('%Y-%m-%d %H:%M:%S') : '') result[4].push(issue_created_on.present? ? issue_created_on.created_on&.strftime('%Y-%m-%d %H:%M:%S') : '')
closed_on_issues = issues.map(&:closed_on).compact closed_on_issues = arr_issue.map(&:closed_on).compact
issue_closed_on = closed_on_issues.max_by { |close_on| close_on } issue_closed_on = closed_on_issues.max_by { |close_on| close_on }
result[5].push(issue_closed_on.present? ? issue_closed_on.strftime('%Y-%m-%d %H:%M:%S') : '') result[5].push(issue_closed_on.present? ? issue_closed_on.strftime('%Y-%m-%d %H:%M:%S') : '')
issue_due_dates = issues.map(&:due_date).compact issue_due_dates = arr_issue.map(&:due_date).compact
issue_due_date = issue_due_dates.max_by { |due_date| due_date } issue_due_date = issue_due_dates.max_by { |due_date| due_date }
result[6].push(issue_due_date.present? ? issue_due_date&.strftime('%Y-%m-%d %H:%M:%S') : '') result[6].push(issue_due_date.present? ? issue_due_date&.strftime('%Y-%m-%d %H:%M:%S') : '')
result[7].push(root_issue.status&.name.present? ? root_issue.status&.name : '') result[7].push(root_issue.status&.name.present? ? root_issue.status&.name : '')
...@@ -118,6 +119,28 @@ module WorkflowReport ...@@ -118,6 +119,28 @@ module WorkflowReport
{ workflow_report: result, error_links: error_links } { workflow_report: result, error_links: error_links }
end end
def build_time_entry_report(project_ids, date_from, date_to)
result = TIME_ENTRY_HEADER.length.times.map { [] }
raw_tasks = WorkflowReportIssue.raw_task_in_date(date_from, date_to, project_ids)
return [] if raw_tasks.empty?
raw_tasks.group_by(&:root_id).each do |root_id, issues|
arr_issue = WorkflowReportIssue.where(root_id: root_id)
result[0] << issues.first.project.name
result[1] << "##{root_id}: #{Issue.find(root_id)&.subject}"
result[3] << arr_issue.map { |issue| issue.time_entries.where("time_entries.spent_on BETWEEN ? AND ?", date_from, date_to).sum(:hours) }.sum.round(2)
request = ''
arr_issue.each do |issue|
jp = issue.custom_values.find_by(custom_field_id: JP_REQUEST_FIELD_ID)&.value
request = jp if jp.present?
end
result[2] << request
end
result
end
private private
def get_process(subject) def get_process(subject)
......
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