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
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