Index: app/models/issue.rb =================================================================== --- app/models/issue.rb (revisión: 83) +++ app/models/issue.rb (copia de trabajo) @@ -27,6 +27,7 @@ belongs_to :fixed_version, :class_name => 'Version', :foreign_key => 'fixed_version_id' belongs_to :priority, :class_name => 'IssuePriority', :foreign_key => 'priority_id' belongs_to :category, :class_name => 'IssueCategory', :foreign_key => 'category_id' + belongs_to :priority_on_children, :class_name => 'IssuePriority', :foreign_key => 'priority_id_on_children' has_many :journals, :as => :journalized, :dependent => :destroy has_many :visible_journals, @@ -64,6 +65,7 @@ delegate :notes, :notes=, :private_notes, :private_notes=, :to => :current_journal, :allow_nil => true validates_presence_of :subject, :priority, :project, :tracker, :author, :status + validates_presence_of :priority_on_children, :if => Proc.new{|i| !i.leaf?} validates_length_of :subject, :maximum => 255 validates_inclusion_of :done_ratio, :in => 0..100 @@ -413,7 +415,7 @@ return if attrs.empty? unless leaf? - attrs.reject! {|k,v| %w(priority_id done_ratio start_date due_date estimated_hours).include?(k)} + attrs.reject! {|k,v| %w(done_ratio).include?(k)} end if attrs['parent_issue_id'].present? @@ -556,7 +558,11 @@ errors.add :tracker_id, :inclusion end end - + + if estimated_hours && estimated_hours_on_children && estimated_hours < estimated_hours_on_children + errors.add :estimated_hours, :less_than_children_estimations + end + # Checks parent issue assignment if @invalid_parent_issue_id.present? errors.add :parent_issue_id, :invalid @@ -573,6 +579,16 @@ errors.add :parent_issue_id, :invalid end end + if errors[:parent_issue_id].empty? + # Parent valid, avoid estimated hours on children overflow estimated hours on parent + ests_on_parent = @parent_issue.estimated_hours_on_children || 0 + ests_on_parent -= estimated_hours_was unless estimated_hours_was.nil? || (parent_id != @parent_issue.id) + if @parent_issue.estimated_hours.nil? && !estimated_hours.nil? + errors.add :estimated_hours, :no_parent_estimations + elsif !estimated_hours.nil? && @parent_issue.estimated_hours < ests_on_parent + estimated_hours + errors.add :estimated_hours, :greater_than_parent_estimations + end + end end end @@ -1200,35 +1216,37 @@ def recalculate_attributes_for(issue_id) if issue_id && p = Issue.find_by_id(issue_id) - # priority = highest priority of children + # priority in children = highest priority of children if priority_position = p.children.maximum("#{IssuePriority.table_name}.position", :joins => :priority) - p.priority = IssuePriority.find_by_position(priority_position) + p.priority_on_children = IssuePriority.find_by_position(priority_position) end - # start/due dates = lowest/highest dates of children - p.start_date = p.children.minimum(:start_date) - p.due_date = p.children.maximum(:due_date) - if p.start_date && p.due_date && p.due_date < p.start_date - p.start_date, p.due_date = p.due_date, p.start_date + # start/due dates on children = lowest/highest dates of children + p.start_date_on_children = p.children.minimum(:start_date) + p.due_date_on_children = p.children.maximum(:due_date) + if p.start_date_on_children && p.due_date_on_children && p.due_date_on_children < p.start_date_on_children + p.start_date_on_children, p.due_date_on_children = p.due_date_on_children, p.start_date_on_children end - + + p_children = Issue.where(:parent_id => p.id) + # done ratio = weighted average ratio of leaves unless Issue.use_status_for_done_ratio? && p.status && p.status.default_done_ratio - leaves_count = p.leaves.count + leaves_count = p_children.count # 1 if leaves_count > 0 - average = p.leaves.average(:estimated_hours).to_f + average = p_children.average(:estimated_hours).to_f # 5 if average == 0 average = 1 end - 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 - progress = done / (average * leaves_count) + 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 + progress = done / p.estimated_hours#(average * leaves_count) p.done_ratio = progress.round end end - # estimate = sum of leaves estimates - p.estimated_hours = p.leaves.sum(:estimated_hours).to_f - p.estimated_hours = nil if p.estimated_hours == 0.0 + # estimate on children = sum of leaves estimates + p.estimated_hours_on_children = p_children.sum(:estimated_hours).to_f + p.estimated_hours_on_children = nil if p.estimated_hours == 0.0 # ancestors will be recursively updated p.save(:validate => false) Index: app/views/issues/show.html.erb =================================================================== --- app/views/issues/show.html.erb (revisión: 83) +++ app/views/issues/show.html.erb (copia de trabajo) @@ -35,6 +35,7 @@ <%= issue_fields_rows do |rows| rows.left l(:field_status), h(@issue.status.name), :class => 'status' rows.left l(:field_priority), h(@issue.priority.name), :class => 'priority' + rows.left l(:field_priority_on_children), h(@issue.priority_on_children.name), :class => 'priority-on-children' unless @issue.leaf? unless @issue.disabled_core_fields.include?('assigned_to_id') 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,9 +49,11 @@ unless @issue.disabled_core_fields.include?('start_date') rows.right l(:field_start_date), format_date(@issue.start_date), :class => 'start-date' + rows.right l(:field_start_date_on_children), format_date(@issue.start_date_on_children), :class => 'start-date-on-children' unless @issue.leaf? end unless @issue.disabled_core_fields.include?('due_date') rows.right l(:field_due_date), format_date(@issue.due_date), :class => 'due-date' + rows.right l(:field_due_date_on_children), format_date(@issue.due_date_on_children), :class => 'due-date-on-children' unless @issue.leaf? end unless @issue.disabled_core_fields.include?('done_ratio') rows.right l(:field_done_ratio), progress_bar(@issue.done_ratio, :width => '80px', :legend => "#{@issue.done_ratio}%"), :class => 'progress' @@ -59,6 +62,9 @@ unless @issue.estimated_hours.nil? rows.right l(:field_estimated_hours), l_hours(@issue.estimated_hours), :class => 'estimated-hours' end + unless @issue.estimated_hours_on_children.nil? + rows.right l(:field_estimated_hours_on_children), l_hours(@issue.estimated_hours_on_children), :class => 'estimated-hours_on_children' unless @issue.leaf? + end end if User.current.allowed_to?(:view_time_entries, @project) 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' Index: app/views/issues/_attributes.html.erb =================================================================== --- app/views/issues/_attributes.html.erb (revisión: 83) +++ app/views/issues/_attributes.html.erb (copia de trabajo) @@ -11,7 +11,7 @@ <% end %> <% if @issue.safe_attribute? 'priority_id' %> -

<%= f.select :priority_id, (@priorities.collect {|p| [p.name, p.id]}), {:required => true}, :disabled => !@issue.leaf? %>

+

<%= f.select :priority_id, (@priorities.collect {|p| [p.name, p.id]}), {:required => true} %>

<% end %> <% if @issue.safe_attribute? 'assigned_to_id' %> @@ -47,15 +47,15 @@ <% end %> <% if @issue.safe_attribute? 'start_date' %> -

<%= f.text_field :start_date, :size => 10, :disabled => !@issue.leaf?, :required => @issue.required_attribute?('start_date') %><%= calendar_for('issue_start_date') if @issue.leaf? %>

+

<%= f.text_field :start_date, :size => 10, :required => @issue.required_attribute?('start_date') %><%= calendar_for('issue_start_date') if @issue.leaf? %>

<% end %> <% if @issue.safe_attribute? 'due_date' %> -

<%= f.text_field :due_date, :size => 10, :disabled => !@issue.leaf?, :required => @issue.required_attribute?('due_date') %><%= calendar_for('issue_due_date') if @issue.leaf? %>

+

<%= f.text_field :due_date, :size => 10, :required => @issue.required_attribute?('due_date') %><%= calendar_for('issue_due_date') if @issue.leaf? %>

<% end %> <% if @issue.safe_attribute? 'estimated_hours' %> -

<%= f.text_field :estimated_hours, :size => 3, :disabled => !@issue.leaf?, :required => @issue.required_attribute?('estimated_hours') %> <%= l(:field_hours) %>

+

<%= f.text_field :estimated_hours, :size => 3, :required => @issue.required_attribute?('estimated_hours') %> <%= l(:field_hours) %>

<% end %> <% if @issue.safe_attribute?('done_ratio') && @issue.leaf? && Issue.use_field_for_done_ratio? %> Index: config/locales/en.yml =================================================================== --- config/locales/en.yml (revisión: 83) +++ config/locales/en.yml (copia de trabajo) @@ -129,6 +129,15 @@ not_same_project: "doesn't belong to the same project" circular_dependency: "This relation would create a circular dependency" cant_link_an_issue_with_a_descendant: "An issue cannot be linked to one of its subtasks" + + models: + # Overrides default messages + issue: + attributes: + estimated_hours: + greater_than_parent_estimations: "is over the parent issue's estimation" + less_than_children_estimations: "is under the estimations of subtasks" + no_parent_estimations: "can't be present if parent issue's estimation is undefined" actionview_instancetag_blank_option: Please select @@ -332,6 +341,10 @@ field_timeout: "Timeout (in seconds)" field_board_parent: Parent forum field_private_notes: Private notes + field_due_date_on_children: Due date on subtasks + field_start_date_on_children: Start date on subtasks + field_priority_on_children: Highest priority on subtasks + field_estimated_hours_on_children: Estimated hours on subtasks setting_app_title: Application title setting_app_subtitle: Application subtitle Index: config/locales/es.yml =================================================================== --- config/locales/es.yml (revisión: 83) +++ config/locales/es.yml (copia de trabajo) @@ -141,10 +141,15 @@ models: # Overrides default messages - + issue: + attributes: + estimated_hours: + greater_than_parent_estimations: "sobrepasa estimaciones de la tarea padre" + less_than_children_estimations: "bajo estimaciones de subtareas" + no_parent_estimations: "no puede estar presente si tarea padre no lo tiene definido" attributes: # Overrides model and default messages. - + direction: ltr date: formats: @@ -275,8 +280,10 @@ field_done_ratio: "% Realizado" field_downloads: Descargas field_due_date: Fecha fin + field_due_date_on_children: Fecha fin en subtareas field_effective_date: Fecha field_estimated_hours: Tiempo estimado + field_estimated_hours_on_children: Tiempo estimado en subtareas field_field_format: Formato field_filename: Fichero field_filesize: Tamaño @@ -315,6 +322,7 @@ field_port: Puerto field_possible_values: Valores posibles field_priority: Prioridad + field_priority_on_children: Prioridad más alta en subtareas field_project: Proyecto field_redirect_existing_links: Redireccionar enlaces existentes field_regexp: Expresión regular @@ -322,6 +330,7 @@ field_searchable: Incluir en las búsquedas field_spent_on: Fecha field_start_date: Fecha de inicio + field_start_date_on_children: Fecha de inicio de subtareas field_start_page: Página principal field_status: Estado field_subject: Asunto Index: 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 =================================================================== --- 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) +++ 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) @@ -0,0 +1,13 @@ +class AddDueDateOnChildrenAndPriorityIdOnChildrenAndStartDateOnChildrenAndEstimatedHoursOnChildrenToIssue < ActiveRecord::Migration + def change + add_column :issues, :due_date_on_children, :date + add_column :issues, :start_date_on_children, :date + add_column :issues, :priority_id_on_children, :integer, :default => 0, :null => false + add_column :issues, :estimated_hours_on_children, :float + add_index :issues, :priority_id_on_children + Issue.all.each do |i| + # Trigger update_parent_attributes + i.update_attributes(:parent_id => i.parent_id) + end + end +end \ No newline at end of file