diff --git a/app/models/work_package/pdf_export/common/common.rb b/app/models/work_package/pdf_export/common/common.rb index 7ebeeb899ef4..7a6c07fc1197 100644 --- a/app/models/work_package/pdf_export/common/common.rb +++ b/app/models/work_package/pdf_export/common/common.rb @@ -285,4 +285,12 @@ def footer_date def current_page_nr pdf.page_number + @page_count - (with_cover? ? 1 : 0) end + + def write_horizontal_line(y_position, height, color) + draw_horizontal_line( + y_position, + pdf.bounds.left, pdf.bounds.right, + height, color + ) + end end diff --git a/modules/reporting/app/controllers/cost_reports_controller.rb b/modules/reporting/app/controllers/cost_reports_controller.rb index 4cdc4b59f227..62ca09c0d943 100644 --- a/modules/reporting/app/controllers/cost_reports_controller.rb +++ b/modules/reporting/app/controllers/cost_reports_controller.rb @@ -76,25 +76,20 @@ def check_cache def index table + return if performed? - perform unless performed? - end - - def perform respond_to do |format| - format.html do - session[session_name].try(:delete, :name) - # get rid of unsaved filters and grouping - store_query(@query) if @query&.id != session[session_name].try(:id) - render locals: { menu_name: project_or_global_menu } - end + format.html { render_html } format.xls { export(:xls) } format.pdf { export(:pdf) } end end - def session_name - report_engine.name.underscore.to_sym + def render_html + session[session_name].try(:delete, :name) + # get rid of unsaved filters and grouping + store_query(@query) if @query&.id != session[session_name].try(:id) + render locals: { menu_name: project_or_global_menu } end def export(format) @@ -546,17 +541,25 @@ def build_query(filters, groups = {}) # Store query in the session def store_query(_query) cookie = {} - cookie[:groups] = @query.group_bys.inject({}) do |h, group| - ((h[:"#{group.type}s"] ||= []) << group.underscore_name.to_sym) && h - end - cookie[:filters] = @query.filters.inject(operators: {}, values: {}) do |h, filter| + cookie[:groups] = cookie_groups + cookie[:filters] = cookie_filters + cookie[:name] = @query.name if @query.name + cookie[:id] = @query.id + session[session_name] = cookie + end + + def cookie_filters + @query.filters.inject(operators: {}, values: {}) do |h, filter| h[:operators][filter.underscore_name.to_sym] = filter.operator.to_s h[:values][filter.underscore_name.to_sym] = filter.values h end - cookie[:name] = @query.name if @query.name - cookie[:id] = @query.id - session[session_name] = cookie + end + + def cookie_groups + @query.group_bys.inject({}) do |h, group| + ((h[:"#{group.type}s"] ||= []) << group.underscore_name.to_sym) && h + end end ## @@ -589,4 +592,8 @@ def find_optional_report(query = "1=0") end rescue ActiveRecord::RecordNotFound end + + def session_name + report_engine.name.underscore.to_sym + end end diff --git a/modules/reporting/app/models/cost_query/sql_statement.rb b/modules/reporting/app/models/cost_query/sql_statement.rb index 973eaf8d14c7..d43b2dc2920c 100644 --- a/modules/reporting/app/models/cost_query/sql_statement.rb +++ b/modules/reporting/app/models/cost_query/sql_statement.rb @@ -74,6 +74,8 @@ def to_s # cost_type_id | -1 | cost_type_id # type | "TimeEntry" | "CostEntry" # count | 1 | 1 + # start_time | start_time | nil + # time_zone | time_zone | nil # # Also: This _should_ handle joining activities and cost_types, as the logic differs for time_entries # and cost_entries. @@ -102,7 +104,7 @@ def self.unified_entry(model) # # @param [CostQuery::SqlStatement] query The statement to adjust def self.unify_time_entries(query) - query.select :activity_id, :logged_by_id, units: :hours, cost_type_id: -1 + query.select :activity_id, :logged_by_id, :start_time, :time_zone, units: :hours, cost_type_id: -1 query.select cost_type: quoted_label(:caption_labor) end @@ -111,7 +113,7 @@ def self.unify_time_entries(query) # # @param [CostQuery::SqlStatement] query The statement to adjust def self.unify_cost_entries(query) - query.select :units, :cost_type_id, :logged_by_id, activity_id: -1 + query.select :units, :cost_type_id, :logged_by_id, activity_id: -1, start_time: nil, time_zone: nil query.select cost_type: "cost_types.name" query.join CostType end diff --git a/modules/reporting/app/workers/cost_query/pdf/timesheet_generator.rb b/modules/reporting/app/workers/cost_query/pdf/timesheet_generator.rb index 1b555edcd46b..aac8e33b6f19 100644 --- a/modules/reporting/app/workers/cost_query/pdf/timesheet_generator.rb +++ b/modules/reporting/app/workers/cost_query/pdf/timesheet_generator.rb @@ -80,30 +80,38 @@ def build_table_rows(entries) .group_by { |r| DateTime.parse(r.fields["spent_on"]) } .sort .each do |spent_on, lines| - day_rows = [] - lines.each do |r| - day_rows.push( - [ - { content: format_date(spent_on), rowspan: r.fields["comments"].present? ? 2 : 1 }, - wp_subject(r.fields["work_package_id"]), - with_times_column? ? "??:00-??:00" : nil, - format_duration(r.fields["units"]), - activity_name(r.fields["activity_id"]) - ].compact - ) - if r.fields["comments"].present? - day_rows.push ([{ content: r.fields["comments"], text_color: "636C76", colspan: table_columns_span }]) - end - end - - # day_rows[0].unshift({ content: format_date(spent_on), rowspan: day_rows.length }) - rows.concat(day_rows) + rows.concat(build_table_day_rows(spent_on, lines)) end rows end # rubocop:enable Metrics/AbcSize + def build_table_day_rows(spent_on, lines) + day_rows = [] + lines.each do |r| + day_rows.push(build_table_row(spent_on, r)) + if r.fields["comments"].present? + day_rows.push(build_table_row_comment(r)) + end + end + day_rows + end + + def build_table_row(spent_on, result_entry) + [ + { content: format_date(spent_on), rowspan: result_entry.fields["comments"].present? ? 2 : 1 }, + wp_subject(result_entry.fields["work_package_id"]), + with_times_column? ? format_spent_on_time(result_entry) : nil, + format_duration(result_entry.fields["units"]), + activity_name(result_entry.fields["activity_id"]) + ].compact + end + + def build_table_row_comment(result_entry) + [{ content: result_entry.fields["comments"], text_color: "636C76", colspan: table_columns_span }] + end + def table_header_columns [ { content: I18n.t(:"activerecord.attributes.time_entry.spent_on"), rowspan: 1 }, @@ -180,6 +188,7 @@ def split_group_rows(table_rows) end groups end + # rubocop:enable Metrics/AbcSize def write_table(user_id, entries) @@ -250,19 +259,12 @@ def sorted_results query.each_direct_result.map(&:itself) end - # rubocop:disable Metrics/AbcSize def write_hr! hr_style = styles.cover_header_border - pdf.stroke do - pdf.line_width = hr_style[:height] - pdf.stroke_color hr_style[:color] - pdf.stroke_horizontal_line pdf.bounds.left, pdf.bounds.right, at: pdf.cursor - end + write_horizontal_line(pdf.cursor, hr_style[:height], hr_style[:color]) pdf.move_down(16) end - # rubocop:enable Metrics/AbcSize - def write_heading! pdf.formatted_text([{ text: heading, size: 26, style: :bold }]) pdf.move_down(2) @@ -291,11 +293,20 @@ def format_duration(hours) "#{hours}h" end + def format_spent_on_time(_result_entry) + # TODO implement times column + # date = result_entry.fields["spent_on"] + # hours = result_entry.fields["units"] + # start_time = result_entry.fields["start_time"] + # time_zone = result_entry.fields["time_zone"] + "" + end + def with_times_column? true end def with_cover? - false + true end end