]> source.dussan.org Git - redmine.git/commitdiff
CSV export added to timelog report (#1009).
authorJean-Philippe Lang <jp_lang@yahoo.fr>
Mon, 7 Apr 2008 17:18:09 +0000 (17:18 +0000)
committerJean-Philippe Lang <jp_lang@yahoo.fr>
Mon, 7 Apr 2008 17:18:09 +0000 (17:18 +0000)
git-svn-id: http://redmine.rubyforge.org/svn/trunk@1338 e93f8b46-1217-0410-a6f0-8f06a7374b81

app/controllers/timelog_controller.rb
app/helpers/timelog_helper.rb
app/views/timelog/report.rhtml
test/functional/timelog_controller_test.rb

index 77337f344344d85f5d65f1dcba4787ff6c514ed4..3081c50dd7cd0eb18cfd6b56f139f592b65e1268 100644 (file)
@@ -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
index 05b55907c6d45e4eb7cc979f605867d94fa25f8d..e0459581dd64d382c3098577f46059329594b42e 100644 (file)
@@ -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
index c29cadf9cdc191472683c643c0b628a3acdbff66..97251bc118310d1928e96d9458cd3bd50570ebcf 100644 (file)
   </tr>
 </tbody>
 </table>
+
+<p class="other-formats">
+<%= l(:label_export_to) %>
+<span><%= link_to 'CSV', params.merge({:format => 'csv'}), :class => 'csv' %></span>
+</p>
 <% end %>
 <% end %>
 
index 6e3308c8495becd4b24bee05fe34aee21d184997..4d6cb0b36bb5237e9b5bfca2e9f8760adf4ad50d 100644 (file)
@@ -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