Project

General

Profile

Feature #6687 » keep_original_dates_and_estimations_on_parent_issue.diff

Bishma Stornelli Ortega, 2013-02-22 21:09

View differences:

app/models/issue.rb (copia de trabajo)
27 27
  belongs_to :fixed_version, :class_name => 'Version', :foreign_key => 'fixed_version_id'
28 28
  belongs_to :priority, :class_name => 'IssuePriority', :foreign_key => 'priority_id'
29 29
  belongs_to :category, :class_name => 'IssueCategory', :foreign_key => 'category_id'
30
  belongs_to :priority_on_children, :class_name => 'IssuePriority', :foreign_key => 'priority_id_on_children'
30 31

  
31 32
  has_many :journals, :as => :journalized, :dependent => :destroy
32 33
  has_many :visible_journals,
......
64 65
  delegate :notes, :notes=, :private_notes, :private_notes=, :to => :current_journal, :allow_nil => true
65 66

  
66 67
  validates_presence_of :subject, :priority, :project, :tracker, :author, :status
68
  validates_presence_of :priority_on_children, :if => Proc.new{|i| !i.leaf?}
67 69

  
68 70
  validates_length_of :subject, :maximum => 255
69 71
  validates_inclusion_of :done_ratio, :in => 0..100
......
413 415
    return if attrs.empty?
414 416

  
415 417
    unless leaf?
416
      attrs.reject! {|k,v| %w(priority_id done_ratio start_date due_date estimated_hours).include?(k)}
418
      attrs.reject! {|k,v| %w(done_ratio).include?(k)}
417 419
    end
418 420

  
419 421
    if attrs['parent_issue_id'].present?
......
556 558
        errors.add :tracker_id, :inclusion
557 559
      end
558 560
    end
559

  
561
    
562
    if estimated_hours && estimated_hours_on_children && estimated_hours < estimated_hours_on_children
563
      errors.add :estimated_hours, :less_than_children_estimations
564
    end
565
    
560 566
    # Checks parent issue assignment
561 567
    if @invalid_parent_issue_id.present?
562 568
      errors.add :parent_issue_id, :invalid
......
573 579
          errors.add :parent_issue_id, :invalid
574 580
        end
575 581
      end
582
      if errors[:parent_issue_id].empty?  
583
        # Parent valid, avoid estimated hours on children overflow estimated hours on parent
584
        ests_on_parent = @parent_issue.estimated_hours_on_children || 0
585
        ests_on_parent -= estimated_hours_was unless estimated_hours_was.nil? || (parent_id != @parent_issue.id) 
586
        if @parent_issue.estimated_hours.nil? && !estimated_hours.nil?
587
          errors.add :estimated_hours, :no_parent_estimations
588
        elsif !estimated_hours.nil? && @parent_issue.estimated_hours < ests_on_parent + estimated_hours
589
          errors.add :estimated_hours, :greater_than_parent_estimations
590
        end
591
      end
576 592
    end
577 593
  end
578 594

  
......
1200 1216

  
1201 1217
  def recalculate_attributes_for(issue_id)
1202 1218
    if issue_id && p = Issue.find_by_id(issue_id)
1203
      # priority = highest priority of children
1219
      # priority in children = highest priority of children
1204 1220
      if priority_position = p.children.maximum("#{IssuePriority.table_name}.position", :joins => :priority)
1205
        p.priority = IssuePriority.find_by_position(priority_position)
1221
        p.priority_on_children = IssuePriority.find_by_position(priority_position)
1206 1222
      end
1207 1223

  
1208
      # start/due dates = lowest/highest dates of children
1209
      p.start_date = p.children.minimum(:start_date)
1210
      p.due_date = p.children.maximum(:due_date)
1211
      if p.start_date && p.due_date && p.due_date < p.start_date
1212
        p.start_date, p.due_date = p.due_date, p.start_date
1224
      # start/due dates on children = lowest/highest dates of children
1225
      p.start_date_on_children = p.children.minimum(:start_date)
1226
      p.due_date_on_children = p.children.maximum(:due_date)
1227
      if p.start_date_on_children && p.due_date_on_children && p.due_date_on_children < p.start_date_on_children
1228
        p.start_date_on_children, p.due_date_on_children = p.due_date_on_children, p.start_date_on_children
1213 1229
      end
1214

  
1230
      
1231
      p_children = Issue.where(:parent_id => p.id)
1232
      
1215 1233
      # done ratio = weighted average ratio of leaves
1216 1234
      unless Issue.use_status_for_done_ratio? && p.status && p.status.default_done_ratio
1217
        leaves_count = p.leaves.count
1235
        leaves_count = p_children.count # 1
1218 1236
        if leaves_count > 0
1219
          average = p.leaves.average(:estimated_hours).to_f
1237
          average = p_children.average(:estimated_hours).to_f # 5
1220 1238
          if average == 0
1221 1239
            average = 1
1222 1240
          end
1223
          done = p.leaves.sum("COALESCE(estimated_hours, #{average}) * (CASE WHEN is_closed = #{connection.quoted_true} THEN 100 ELSE COALESCE(done_ratio, 0) END)", :joins => :status).to_f
1224
          progress = done / (average * leaves_count)
1241
          done = p_children.sum("COALESCE(estimated_hours, #{average}) * (CASE WHEN is_closed = #{connection.quoted_true} THEN 100 ELSE COALESCE(done_ratio, 0) END)", :joins => :status).to_f
1242
          progress = done / p.estimated_hours#(average * leaves_count)
1225 1243
          p.done_ratio = progress.round
1226 1244
        end
1227 1245
      end
1228 1246

  
1229
      # estimate = sum of leaves estimates
1230
      p.estimated_hours = p.leaves.sum(:estimated_hours).to_f
1231
      p.estimated_hours = nil if p.estimated_hours == 0.0
1247
      # estimate on children = sum of leaves estimates
1248
      p.estimated_hours_on_children = p_children.sum(:estimated_hours).to_f
1249
      p.estimated_hours_on_children = nil if p.estimated_hours == 0.0
1232 1250

  
1233 1251
      # ancestors will be recursively updated
1234 1252
      p.save(:validate => false)
app/views/issues/show.html.erb (copia de trabajo)
35 35
<%= issue_fields_rows do |rows|
36 36
  rows.left l(:field_status), h(@issue.status.name), :class => 'status'
37 37
  rows.left l(:field_priority), h(@issue.priority.name), :class => 'priority'
38
  rows.left l(:field_priority_on_children), h(@issue.priority_on_children.name), :class => 'priority-on-children' unless @issue.leaf?
38 39

  
39 40
  unless @issue.disabled_core_fields.include?('assigned_to_id')
40 41
    rows.left l(:field_assigned_to), avatar(@issue.assigned_to, :size => "14").to_s.html_safe + (@issue.assigned_to ? link_to_user(@issue.assigned_to) : "-"), :class => 'assigned-to'
......
48 49

  
49 50
  unless @issue.disabled_core_fields.include?('start_date')
50 51
    rows.right l(:field_start_date), format_date(@issue.start_date), :class => 'start-date'
52
    rows.right l(:field_start_date_on_children), format_date(@issue.start_date_on_children), :class => 'start-date-on-children' unless @issue.leaf?
51 53
  end
52 54
  unless @issue.disabled_core_fields.include?('due_date')
53 55
    rows.right l(:field_due_date), format_date(@issue.due_date), :class => 'due-date'
56
    rows.right l(:field_due_date_on_children), format_date(@issue.due_date_on_children), :class => 'due-date-on-children' unless @issue.leaf?
54 57
  end
55 58
  unless @issue.disabled_core_fields.include?('done_ratio')
56 59
    rows.right l(:field_done_ratio), progress_bar(@issue.done_ratio, :width => '80px', :legend => "#{@issue.done_ratio}%"), :class => 'progress'
......
59 62
    unless @issue.estimated_hours.nil?
60 63
      rows.right l(:field_estimated_hours), l_hours(@issue.estimated_hours), :class => 'estimated-hours'
61 64
    end
65
    unless @issue.estimated_hours_on_children.nil?
66
      rows.right l(:field_estimated_hours_on_children), l_hours(@issue.estimated_hours_on_children), :class => 'estimated-hours_on_children' unless @issue.leaf?
67
    end
62 68
  end
63 69
  if User.current.allowed_to?(:view_time_entries, @project)
64 70
    rows.right l(:label_spent_time), (@issue.total_spent_hours > 0 ? (link_to l_hours(@issue.total_spent_hours), {:controller => 'timelog', :action => 'index', :project_id => @project, :issue_id => @issue}) : "-"), :class => 'spent-time'
app/views/issues/_attributes.html.erb (copia de trabajo)
11 11
<% end %>
12 12

  
13 13
<% if @issue.safe_attribute? 'priority_id' %>
14
<p><%= f.select :priority_id, (@priorities.collect {|p| [p.name, p.id]}), {:required => true}, :disabled => !@issue.leaf? %></p>
14
<p><%= f.select :priority_id, (@priorities.collect {|p| [p.name, p.id]}), {:required => true} %></p>
15 15
<% end %>
16 16

  
17 17
<% if @issue.safe_attribute? 'assigned_to_id' %>
......
47 47
<% end %>
48 48

  
49 49
<% if @issue.safe_attribute? 'start_date' %>
50
<p><%= f.text_field :start_date, :size => 10, :disabled => !@issue.leaf?, :required => @issue.required_attribute?('start_date') %><%= calendar_for('issue_start_date') if @issue.leaf? %></p>
50
<p><%= f.text_field :start_date, :size => 10, :required => @issue.required_attribute?('start_date') %><%= calendar_for('issue_start_date') if @issue.leaf? %></p>
51 51
<% end %>
52 52

  
53 53
<% if @issue.safe_attribute? 'due_date' %>
54
<p><%= f.text_field :due_date, :size => 10, :disabled => !@issue.leaf?, :required => @issue.required_attribute?('due_date') %><%= calendar_for('issue_due_date') if @issue.leaf? %></p>
54
<p><%= f.text_field :due_date, :size => 10, :required => @issue.required_attribute?('due_date') %><%= calendar_for('issue_due_date') if @issue.leaf? %></p>
55 55
<% end %>
56 56

  
57 57
<% if @issue.safe_attribute? 'estimated_hours' %>
58
<p><%= f.text_field :estimated_hours, :size => 3, :disabled => !@issue.leaf?, :required => @issue.required_attribute?('estimated_hours') %> <%= l(:field_hours) %></p>
58
<p><%= f.text_field :estimated_hours, :size => 3, :required => @issue.required_attribute?('estimated_hours') %> <%= l(:field_hours) %></p>
59 59
<% end %>
60 60

  
61 61
<% if @issue.safe_attribute?('done_ratio') && @issue.leaf? && Issue.use_field_for_done_ratio? %>
config/locales/en.yml (copia de trabajo)
129 129
        not_same_project: "doesn't belong to the same project"
130 130
        circular_dependency: "This relation would create a circular dependency"
131 131
        cant_link_an_issue_with_a_descendant: "An issue cannot be linked to one of its subtasks"
132
        
133
      models:
134
        # Overrides default messages
135
        issue:
136
          attributes:
137
            estimated_hours:
138
              greater_than_parent_estimations: "is over the parent issue's estimation"
139
              less_than_children_estimations: "is under the estimations of subtasks"
140
              no_parent_estimations: "can't be present if parent issue's estimation is undefined"
132 141

  
133 142
  actionview_instancetag_blank_option: Please select
134 143

  
......
332 341
  field_timeout: "Timeout (in seconds)"
333 342
  field_board_parent: Parent forum
334 343
  field_private_notes: Private notes
344
  field_due_date_on_children: Due date on subtasks
345
  field_start_date_on_children: Start date on subtasks
346
  field_priority_on_children: Highest priority on subtasks
347
  field_estimated_hours_on_children: Estimated hours on subtasks
335 348

  
336 349
  setting_app_title: Application title
337 350
  setting_app_subtitle: Application subtitle
config/locales/es.yml (copia de trabajo)
141 141

  
142 142
      models:
143 143
        # Overrides default messages
144

  
144
        issue:
145
          attributes:
146
            estimated_hours:
147
              greater_than_parent_estimations: "sobrepasa estimaciones de la tarea padre"
148
              less_than_children_estimations: "bajo estimaciones de subtareas"
149
              no_parent_estimations: "no puede estar presente si tarea padre no lo tiene definido"
145 150
      attributes:
146 151
        # Overrides model and default messages.
147

  
152
        
148 153
  direction: ltr
149 154
  date:
150 155
    formats:
......
275 280
  field_done_ratio: "% Realizado"
276 281
  field_downloads: Descargas
277 282
  field_due_date: Fecha fin
283
  field_due_date_on_children: Fecha fin en subtareas
278 284
  field_effective_date: Fecha
279 285
  field_estimated_hours: Tiempo estimado
286
  field_estimated_hours_on_children: Tiempo estimado en subtareas
280 287
  field_field_format: Formato
281 288
  field_filename: Fichero
282 289
  field_filesize: Tamaño
......
315 322
  field_port: Puerto
316 323
  field_possible_values: Valores posibles
317 324
  field_priority: Prioridad
325
  field_priority_on_children: Prioridad más alta en subtareas 
318 326
  field_project: Proyecto
319 327
  field_redirect_existing_links: Redireccionar enlaces existentes
320 328
  field_regexp: Expresión regular
......
322 330
  field_searchable: Incluir en las búsquedas
323 331
  field_spent_on: Fecha
324 332
  field_start_date: Fecha de inicio
333
  field_start_date_on_children: Fecha de inicio de subtareas
325 334
  field_start_page: Página principal
326 335
  field_status: Estado
327 336
  field_subject: Asunto
db/migrate/20130222154546_add_due_date_on_children_and_priority_id_on_children_and_start_date_on_children_and_estimated_hours_on_children_to_issue.rb (revisión: 0)
1
class AddDueDateOnChildrenAndPriorityIdOnChildrenAndStartDateOnChildrenAndEstimatedHoursOnChildrenToIssue < ActiveRecord::Migration
2
  def change
3
    add_column :issues, :due_date_on_children, :date
4
    add_column :issues, :start_date_on_children, :date
5
    add_column :issues, :priority_id_on_children, :integer, :default => 0, :null => false
6
    add_column :issues, :estimated_hours_on_children, :float
7
    add_index :issues, :priority_id_on_children
8
    Issue.all.each do |i|
9
      # Trigger update_parent_attributes
10
      i.update_attributes(:parent_id => i.parent_id)
11
    end
12
  end
13
end
(2-2/4)