From 5d3454853956adee21518a1fc891b26f36c3c294 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Lang Date: Mon, 7 Apr 2008 17:18:09 +0000 Subject: [PATCH] CSV export added to timelog report (#1009). git-svn-id: http://redmine.rubyforge.org/svn/trunk@1338 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/controllers/timelog_controller.rb | 5 ++- app/helpers/timelog_helper.rb | 52 ++++++++++++++++++++++ app/views/timelog/report.rhtml | 5 +++ test/functional/timelog_controller_test.rb | 13 +++++- 4 files changed, 73 insertions(+), 2 deletions(-) diff --git a/app/controllers/timelog_controller.rb b/app/controllers/timelog_controller.rb index 77337f344..3081c50dd 100644 --- a/app/controllers/timelog_controller.rb +++ b/app/controllers/timelog_controller.rb @@ -112,7 +112,10 @@ class TimelogController < ApplicationController end end - render :layout => false if request.xhr? + respond_to do |format| + format.html { render :layout => !request.xhr? } + format.csv { send_data(report_to_csv(@criterias, @periods, @hours).read, :type => 'text/csv; header=present', :filename => 'timelog.csv') } + end end def details diff --git a/app/helpers/timelog_helper.rb b/app/helpers/timelog_helper.rb index 05b55907c..e0459581d 100644 --- a/app/helpers/timelog_helper.rb +++ b/app/helpers/timelog_helper.rb @@ -76,4 +76,56 @@ module TimelogHelper export.rewind export end + + def report_to_csv(criterias, periods, hours) + export = StringIO.new + CSV::Writer.generate(export, l(:general_csv_separator)) do |csv| + # Column headers + headers = criterias.collect {|criteria| l(@available_criterias[criteria][:label]) } + headers += periods + headers << l(:label_total) + csv << headers.collect {|c| to_utf8(c) } + # Content + report_criteria_to_csv(csv, criterias, periods, hours) + # Total row + row = [ l(:label_total) ] + [''] * (criterias.size - 1) + total = 0 + periods.each do |period| + sum = sum_hours(select_hours(hours, @columns, period.to_s)) + total += sum + row << (sum > 0 ? "%.2f" % sum : '') + end + row << "%.2f" %total + csv << row + end + export.rewind + export + end + + def report_criteria_to_csv(csv, criterias, periods, hours, level=0) + hours.collect {|h| h[criterias[level]]}.uniq.each do |value| + hours_for_value = select_hours(hours, criterias[level], value) + next if hours_for_value.empty? + row = [''] * level + row << to_utf8(value.nil? ? l(:label_none) : @available_criterias[criterias[level]][:klass].find_by_id(value)) + row += [''] * (criterias.length - level - 1) + total = 0 + periods.each do |period| + sum = sum_hours(select_hours(hours_for_value, @columns, period.to_s)) + total += sum + row << (sum > 0 ? "%.2f" % sum : '') + end + row << "%.2f" %total + csv << row + + if criterias.length > level + 1 + report_criteria_to_csv(csv, criterias, periods, hours_for_value, level + 1) + end + end + end + + def to_utf8(s) + @ic ||= Iconv.new(l(:general_csv_encoding), 'UTF-8') + begin; @ic.iconv(s.to_s); rescue; s.to_s; end + end end diff --git a/app/views/timelog/report.rhtml b/app/views/timelog/report.rhtml index c29cadf9c..97251bc11 100644 --- a/app/views/timelog/report.rhtml +++ b/app/views/timelog/report.rhtml @@ -60,6 +60,11 @@ + +

+<%= l(:label_export_to) %> +<%= link_to 'CSV', params.merge({:format => 'csv'}), :class => 'csv' %> +

<% end %> <% end %> diff --git a/test/functional/timelog_controller_test.rb b/test/functional/timelog_controller_test.rb index 6e3308c84..4d6cb0b36 100644 --- a/test/functional/timelog_controller_test.rb +++ b/test/functional/timelog_controller_test.rb @@ -118,7 +118,18 @@ class TimelogControllerTest < Test::Unit::TestCase assert_template 'report' assert_not_nil assigns(:total_hours) assert_equal "0.00", "%.2f" % assigns(:total_hours) - end + end + + def test_report_csv_export + get :report, :project_id => 1, :columns => 'month', :from => "2007-01-01", :to => "2007-06-30", :criterias => ["project", "member", "activity"], :format => "csv" + assert_response :success + assert_equal 'text/csv', @response.content_type + lines = @response.body.chomp.split("\n") + # Headers + assert_equal 'Project,Member,Activity,2007-1,2007-2,2007-3,2007-4,2007-5,2007-6,Total', lines.first + # Total row + assert_equal 'Total,"","","","",154.25,8.65,"","",162.90', lines.last + end def test_details_at_project_level get :details, :project_id => 1 -- 2.39.5