Project

General

Profile

« Previous | Next » 

Revision 12380

Move format specific statements to Redmine::FieldFormat.

View differences:

sandbox/custom_fields/app/models/custom_field.rb
159 159
  # Returns nil if the custom field can not be used for sorting.
160 160
  def order_statement
161 161
    return nil if multiple?
162
    case field_format
163
      when 'string', 'text', 'list', 'date', 'bool'
164
        # COALESCE is here to make sure that blank and NULL values are sorted equally
165
        "COALESCE(#{join_alias}.value, '')"
166
      when 'int', 'float'
167
        # Make the database cast values into numeric
168
        # Postgresql will raise an error if a value can not be casted!
169
        # CustomValue validations should ensure that it doesn't occur
170
        "CAST(CASE #{join_alias}.value WHEN '' THEN '0' ELSE #{join_alias}.value END AS decimal(30,3))"
171
      when 'user', 'version'
172
        value_class.fields_for_order_statement(value_join_alias)
173
      else
174
        nil
175
    end
162
    format.order_statement(self)
176 163
  end
177 164

  
178 165
  # Returns a GROUP BY clause that can used to group by custom value
179 166
  # Returns nil if the custom field can not be used for grouping.
180 167
  def group_statement
181 168
    return nil if multiple?
182
    case field_format
183
      when 'list', 'date', 'bool', 'int'
184
        order_statement
185
      when 'user', 'version'
186
        "COALESCE(#{join_alias}.value, '')"
187
      else
188
        nil
189
    end
169
    format.group_statement(self)
190 170
  end
191 171

  
192 172
  def join_for_order_statement
193
    case field_format
194
      when 'user', 'version'
195
        "LEFT OUTER JOIN #{CustomValue.table_name} #{join_alias}" +
196
          " ON #{join_alias}.customized_type = '#{self.class.customized_class.base_class.name}'" +
197
          " AND #{join_alias}.customized_id = #{self.class.customized_class.table_name}.id" +
198
          " AND #{join_alias}.custom_field_id = #{id}" +
199
          " AND (#{visibility_by_project_condition})" +
200
          " AND #{join_alias}.value <> ''" +
201
          " AND #{join_alias}.id = (SELECT max(#{join_alias}_2.id) FROM #{CustomValue.table_name} #{join_alias}_2" +
202
            " WHERE #{join_alias}_2.customized_type = #{join_alias}.customized_type" +
203
            " AND #{join_alias}_2.customized_id = #{join_alias}.customized_id" +
204
            " AND #{join_alias}_2.custom_field_id = #{join_alias}.custom_field_id)" +
205
          " LEFT OUTER JOIN #{value_class.table_name} #{value_join_alias}" +
206
          " ON CAST(CASE #{join_alias}.value WHEN '' THEN '0' ELSE #{join_alias}.value END AS decimal(30,0)) = #{value_join_alias}.id"
207
      when 'int', 'float'
208
        "LEFT OUTER JOIN #{CustomValue.table_name} #{join_alias}" +
209
          " ON #{join_alias}.customized_type = '#{self.class.customized_class.base_class.name}'" +
210
          " AND #{join_alias}.customized_id = #{self.class.customized_class.table_name}.id" +
211
          " AND #{join_alias}.custom_field_id = #{id}" +
212
          " AND (#{visibility_by_project_condition})" +
213
          " AND #{join_alias}.value <> ''" +
214
          " AND #{join_alias}.id = (SELECT max(#{join_alias}_2.id) FROM #{CustomValue.table_name} #{join_alias}_2" +
215
            " WHERE #{join_alias}_2.customized_type = #{join_alias}.customized_type" +
216
            " AND #{join_alias}_2.customized_id = #{join_alias}.customized_id" +
217
            " AND #{join_alias}_2.custom_field_id = #{join_alias}.custom_field_id)"
218
      when 'string', 'text', 'list', 'date', 'bool'
219
        "LEFT OUTER JOIN #{CustomValue.table_name} #{join_alias}" +
220
          " ON #{join_alias}.customized_type = '#{self.class.customized_class.base_class.name}'" +
221
          " AND #{join_alias}.customized_id = #{self.class.customized_class.table_name}.id" +
222
          " AND #{join_alias}.custom_field_id = #{id}" +
223
          " AND (#{visibility_by_project_condition})" +
224
          " AND #{join_alias}.id = (SELECT max(#{join_alias}_2.id) FROM #{CustomValue.table_name} #{join_alias}_2" +
225
            " WHERE #{join_alias}_2.customized_type = #{join_alias}.customized_type" +
226
            " AND #{join_alias}_2.customized_id = #{join_alias}.customized_id" +
227
            " AND #{join_alias}_2.custom_field_id = #{join_alias}.custom_field_id)"
228
      else
229
        nil
230
    end
173
    format.join_for_order_statement(self)
231 174
  end
232 175

  
233
  def join_alias
234
    "cf_#{id}"
235
  end
236

  
237
  def value_join_alias
238
    join_alias + "_" + field_format
239
  end
240

  
241 176
  def visibility_by_project_condition(project_key=nil, user=User.current)
242 177
    if visible? || user.admin?
243 178
      "1=1"
sandbox/custom_fields/lib/redmine/field_format.rb
175 175

  
176 176
      def before_custom_field_save(custom_field)
177 177
      end
178

  
179
      # Returns a ORDER BY clause that can used to sort customized
180
      # objects by their value of the custom field.
181
      # Returns nil if the custom field can not be used for sorting.
182
      def order_statement(custom_field)
183
        # COALESCE is here to make sure that blank and NULL values are sorted equally
184
        "COALESCE(#{join_alias custom_field}.value, '')"
185
      end
186

  
187
      # Returns a GROUP BY clause that can used to group by custom value
188
      # Returns nil if the custom field can not be used for grouping.
189
      def group_statement(custom_field)
190
        nil
191
      end
192

  
193
      # Returns a JOIN clause that is added to the query when sorting by custom values
194
      def join_for_order_statement(custom_field)
195
        alias_name = join_alias(custom_field)
196

  
197
        "LEFT OUTER JOIN #{CustomValue.table_name} #{alias_name}" +
198
          " ON #{alias_name}.customized_type = '#{custom_field.class.customized_class.base_class.name}'" +
199
          " AND #{alias_name}.customized_id = #{custom_field.class.customized_class.table_name}.id" +
200
          " AND #{alias_name}.custom_field_id = #{custom_field.id}" +
201
          " AND (#{custom_field.visibility_by_project_condition})" +
202
          " AND #{alias_name}.value <> ''" +
203
          " AND #{alias_name}.id = (SELECT max(#{alias_name}_2.id) FROM #{CustomValue.table_name} #{alias_name}_2" +
204
            " WHERE #{alias_name}_2.customized_type = #{alias_name}.customized_type" +
205
            " AND #{alias_name}_2.customized_id = #{alias_name}.customized_id" +
206
            " AND #{alias_name}_2.custom_field_id = #{alias_name}.custom_field_id)"
207
      end
208

  
209
      def join_alias(custom_field)
210
        "cf_#{custom_field.id}"
211
      end
212
      protected :join_alias
178 213
    end
179 214

  
180 215
    class Unbounded < Base
......
278 313

  
279 314
    class Numeric < Unbounded
280 315
      self.form_partial = 'custom_fields/formats/numeric'
316

  
317
      def order_statement(custom_field)
318
        # Make the database cast values into numeric
319
        # Postgresql will raise an error if a value can not be casted!
320
        # CustomValue validations should ensure that it doesn't occur
321
        "CAST(CASE #{join_alias custom_field}.value WHEN '' THEN '0' ELSE #{join_alias custom_field}.value END AS decimal(30,3))"
322
      end
281 323
    end
282 324

  
283 325
    class IntFormat < Numeric
......
300 342
      def query_filter_options(custom_field, query)
301 343
        {:type => :integer}
302 344
      end
345

  
346
      def group_statement(custom_field)
347
        order_statement(custom_field)
348
      end
303 349
    end
304 350

  
305 351
    class FloatFormat < Numeric
......
350 396
      def query_filter_options(custom_field, query)
351 397
        {:type => :date}
352 398
      end
399

  
400
      def group_statement(custom_field)
401
        order_statement(custom_field)
402
      end
353 403
    end
354 404

  
355 405
    class BoolFormat < Base
......
385 435
      def query_filter_options(custom_field, query)
386 436
        {:type => :list, :values => possible_values_options(custom_field)}
387 437
      end
438

  
439
      def group_statement(custom_field)
440
        order_statement(custom_field)
441
      end
388 442
    end
389 443

  
390 444
    class List < Base
......
451 505
          []
452 506
        end
453 507
      end
508

  
509
      def group_statement(custom_field)
510
        order_statement(custom_field)
511
      end
454 512
    end
455 513

  
456 514
    class RecordList < List
......
473 531
        end
474 532
        options
475 533
      end
534

  
535
      def order_statement(custom_field)
536
        if target_class.respond_to?(:fields_for_order_statement)
537
          target_class.fields_for_order_statement(value_join_alias(custom_field))
538
        end
539
      end
540

  
541
      def group_statement(custom_field)
542
        "COALESCE(#{join_alias custom_field}.value, '')"
543
      end
544

  
545
      def join_for_order_statement(custom_field)
546
        alias_name = join_alias(custom_field)
547

  
548
        "LEFT OUTER JOIN #{CustomValue.table_name} #{alias_name}" +
549
          " ON #{alias_name}.customized_type = '#{custom_field.class.customized_class.base_class.name}'" +
550
          " AND #{alias_name}.customized_id = #{custom_field.class.customized_class.table_name}.id" +
551
          " AND #{alias_name}.custom_field_id = #{custom_field.id}" +
552
          " AND (#{custom_field.visibility_by_project_condition})" +
553
          " AND #{alias_name}.value <> ''" +
554
          " AND #{alias_name}.id = (SELECT max(#{alias_name}_2.id) FROM #{CustomValue.table_name} #{alias_name}_2" +
555
            " WHERE #{alias_name}_2.customized_type = #{alias_name}.customized_type" +
556
            " AND #{alias_name}_2.customized_id = #{alias_name}.customized_id" +
557
            " AND #{alias_name}_2.custom_field_id = #{alias_name}.custom_field_id)" +
558
          " LEFT OUTER JOIN #{target_class.table_name} #{value_join_alias custom_field}" +
559
          " ON CAST(CASE #{alias_name}.value WHEN '' THEN '0' ELSE #{alias_name}.value END AS decimal(30,0)) = #{value_join_alias custom_field}.id"
560
      end
561

  
562
      def value_join_alias(custom_field)
563
        join_alias(custom_field) + "_" + custom_field.field_format
564
      end
565
      protected :value_join_alias
476 566
    end
477 567

  
478 568
    class UserFormat < RecordList
sandbox/custom_fields/lib/redmine/helpers/time_report.rb
138 138

  
139 139
        # Add list and boolean custom fields as available criteria
140 140
        custom_fields.select {|cf| %w(list bool).include? cf.field_format }.each do |cf|
141
          @available_criteria["cf_#{cf.id}"] = {:sql => "#{cf.join_alias}.value",
141
          @available_criteria["cf_#{cf.id}"] = {:sql => cf.group_statement,
142 142
                                                 :joins => cf.join_for_order_statement,
143 143
                                                 :format => cf.field_format,
144 144
                                                 :custom_field => cf,

Also available in: Unified diff