]> source.dussan.org Git - redmine.git/commitdiff
Merged r14944 (#21413).
authorJean-Philippe Lang <jp_lang@yahoo.fr>
Sat, 5 Dec 2015 10:12:54 +0000 (10:12 +0000)
committerJean-Philippe Lang <jp_lang@yahoo.fr>
Sat, 5 Dec 2015 10:12:54 +0000 (10:12 +0000)
git-svn-id: http://svn.redmine.org/redmine/branches/3.2-stable@14945 e93f8b46-1217-0410-a6f0-8f06a7374b81

app/models/custom_field.rb
app/models/query.rb
lib/redmine/field_format.rb

index a1373d12b95ba015ee3798a5579c8892f0622896..8da75031dca7b9ab2f8073390678e2066c6a94fa 100644 (file)
@@ -153,6 +153,10 @@ class CustomField < ActiveRecord::Base
     format.query_filter_options(self, query)
   end
 
+  def totalable?
+    format.totalable_supported
+  end
+
   # Returns a ORDER BY clause that can used to sort customized
   # objects by their value of the custom field.
   # Returns nil if the custom field can not be used for sorting.
index 0ba7a8c4bb4d6a99719029bd9faff61313e52f49..ddc59f99b9f11b113cee9fa89e996345808577dd 100644 (file)
@@ -80,7 +80,7 @@ class QueryCustomFieldColumn < QueryColumn
     self.name = "cf_#{custom_field.id}".to_sym
     self.sortable = custom_field.order_statement || false
     self.groupable = custom_field.group_statement || false
-    self.totalable = ['int', 'float'].include?(custom_field.field_format)
+    self.totalable = custom_field.totalable?
     @inline = true
     @cf = custom_field
   end
@@ -692,7 +692,7 @@ class Query < ActiveRecord::Base
     end
     if column.is_a?(QueryCustomFieldColumn)
       custom_field = column.custom_field
-      send "total_for_#{custom_field.field_format}_custom_field", custom_field, scope
+      send "total_for_custom_field", custom_field, scope
     else
       send "total_for_#{column.name}", scope
     end
@@ -710,21 +710,9 @@ class Query < ActiveRecord::Base
       group(group_by_statement)
   end
 
-  def total_for_float_custom_field(custom_field, scope)
-    total_for_custom_field(custom_field, scope) {|t| t.to_f.round(2)}
-  end
-
-  def total_for_int_custom_field(custom_field, scope)
-    total_for_custom_field(custom_field, scope) {|t| t.to_i}
-  end
-
   def total_for_custom_field(custom_field, scope, &block)
-    total = scope.joins(:custom_values).
-      where(:custom_values => {:custom_field_id => custom_field.id}).
-      where.not(:custom_values => {:value => ''}).
-      sum("CAST(#{CustomValue.table_name}.value AS decimal(30,3))")
-
-    total = map_total(total, &block) if block_given?
+    total = custom_field.format.total_for_scope(custom_field, scope)
+    total = map_total(total) {|t| custom_field.format.cast_total_value(custom_field, t)}
     total
   end
 
index 841d6a08d9f27952e9fd56b364b9214bff4933db..10e5b48a0f5edac45b47a40a7d2b1ae233e9e116 100644 (file)
@@ -61,6 +61,10 @@ module Redmine
       class_attribute :searchable_supported
       self.searchable_supported = false
 
+      # Set this to true if field values can be summed up
+      class_attribute :totalable_supported
+      self.totalable_supported = false
+
       # Restricts the classes that the custom field can be added to
       # Set to nil for no restrictions
       class_attribute :customized_class_names
@@ -370,6 +374,7 @@ module Redmine
 
     class Numeric < Unbounded
       self.form_partial = 'custom_fields/formats/numeric'
+      self.totalable_supported = true
 
       def order_statement(custom_field)
         # Make the database cast values into numeric
@@ -377,6 +382,18 @@ module Redmine
         # CustomValue validations should ensure that it doesn't occur
         "CAST(CASE #{join_alias custom_field}.value WHEN '' THEN '0' ELSE #{join_alias custom_field}.value END AS decimal(30,3))"
       end
+
+      # Returns totals for the given scope
+      def total_for_scope(custom_field, scope)
+        scope.joins(:custom_values).
+          where(:custom_values => {:custom_field_id => custom_field.id}).
+          where.not(:custom_values => {:value => ''}).
+          sum("CAST(#{CustomValue.table_name}.value AS decimal(30,3))")
+      end
+
+      def cast_total_value(custom_field, value)
+        cast_single_value(custom_field, value)
+      end
     end
 
     class IntFormat < Numeric
@@ -412,6 +429,10 @@ module Redmine
         value.to_f
       end
 
+      def cast_total_value(custom_field, value)
+        value.to_f.round(2)
+      end
+
       def validate_single_value(custom_field, value, customized=nil)
         errs = super
         errs << ::I18n.t('activerecord.errors.messages.invalid') unless (Kernel.Float(value) rescue nil)