##// END OF EJS Templates
Merged r14944 (#21413)....
Jean-Philippe Lang -
r14563:f2fd7905557d
parent child
Show More
@@ -153,6 +153,10 class CustomField < ActiveRecord::Base
153 153 format.query_filter_options(self, query)
154 154 end
155 155
156 def totalable?
157 format.totalable_supported
158 end
159
156 160 # Returns a ORDER BY clause that can used to sort customized
157 161 # objects by their value of the custom field.
158 162 # Returns nil if the custom field can not be used for sorting.
@@ -80,7 +80,7 class QueryCustomFieldColumn < QueryColumn
80 80 self.name = "cf_#{custom_field.id}".to_sym
81 81 self.sortable = custom_field.order_statement || false
82 82 self.groupable = custom_field.group_statement || false
83 self.totalable = ['int', 'float'].include?(custom_field.field_format)
83 self.totalable = custom_field.totalable?
84 84 @inline = true
85 85 @cf = custom_field
86 86 end
@@ -692,7 +692,7 class Query < ActiveRecord::Base
692 692 end
693 693 if column.is_a?(QueryCustomFieldColumn)
694 694 custom_field = column.custom_field
695 send "total_for_#{custom_field.field_format}_custom_field", custom_field, scope
695 send "total_for_custom_field", custom_field, scope
696 696 else
697 697 send "total_for_#{column.name}", scope
698 698 end
@@ -710,21 +710,9 class Query < ActiveRecord::Base
710 710 group(group_by_statement)
711 711 end
712 712
713 def total_for_float_custom_field(custom_field, scope)
714 total_for_custom_field(custom_field, scope) {|t| t.to_f.round(2)}
715 end
716
717 def total_for_int_custom_field(custom_field, scope)
718 total_for_custom_field(custom_field, scope) {|t| t.to_i}
719 end
720
721 713 def total_for_custom_field(custom_field, scope, &block)
722 total = scope.joins(:custom_values).
723 where(:custom_values => {:custom_field_id => custom_field.id}).
724 where.not(:custom_values => {:value => ''}).
725 sum("CAST(#{CustomValue.table_name}.value AS decimal(30,3))")
726
727 total = map_total(total, &block) if block_given?
714 total = custom_field.format.total_for_scope(custom_field, scope)
715 total = map_total(total) {|t| custom_field.format.cast_total_value(custom_field, t)}
728 716 total
729 717 end
730 718
@@ -61,6 +61,10 module Redmine
61 61 class_attribute :searchable_supported
62 62 self.searchable_supported = false
63 63
64 # Set this to true if field values can be summed up
65 class_attribute :totalable_supported
66 self.totalable_supported = false
67
64 68 # Restricts the classes that the custom field can be added to
65 69 # Set to nil for no restrictions
66 70 class_attribute :customized_class_names
@@ -370,6 +374,7 module Redmine
370 374
371 375 class Numeric < Unbounded
372 376 self.form_partial = 'custom_fields/formats/numeric'
377 self.totalable_supported = true
373 378
374 379 def order_statement(custom_field)
375 380 # Make the database cast values into numeric
@@ -377,6 +382,18 module Redmine
377 382 # CustomValue validations should ensure that it doesn't occur
378 383 "CAST(CASE #{join_alias custom_field}.value WHEN '' THEN '0' ELSE #{join_alias custom_field}.value END AS decimal(30,3))"
379 384 end
385
386 # Returns totals for the given scope
387 def total_for_scope(custom_field, scope)
388 scope.joins(:custom_values).
389 where(:custom_values => {:custom_field_id => custom_field.id}).
390 where.not(:custom_values => {:value => ''}).
391 sum("CAST(#{CustomValue.table_name}.value AS decimal(30,3))")
392 end
393
394 def cast_total_value(custom_field, value)
395 cast_single_value(custom_field, value)
396 end
380 397 end
381 398
382 399 class IntFormat < Numeric
@@ -412,6 +429,10 module Redmine
412 429 value.to_f
413 430 end
414 431
432 def cast_total_value(custom_field, value)
433 value.to_f.round(2)
434 end
435
415 436 def validate_single_value(custom_field, value, customized=nil)
416 437 errs = super
417 438 errs << ::I18n.t('activerecord.errors.messages.invalid') unless (Kernel.Float(value) rescue nil)
General Comments 0
You need to be logged in to leave comments. Login now