Index: app/models/issue.rb =================================================================== --- app/models/issue.rb (revision 1680) +++ app/models/issue.rb (working copy) @@ -113,6 +113,14 @@ if start_date && soonest_start && start_date < soonest_start errors.add :start_date, :activerecord_error_invalid end + + if fixed_version_id + #status and version have to retrieved from their id, because the objects only get updated upon saving + new_status = IssueStatus.find_by_id(status_id) + if !new_status.is_closed? && Version.find_by_id(fixed_version_id).completed? + errors.add :fixed_version, :activerecord_error_version_completed + end + end end def validate_on_create Index: app/models/version.rb =================================================================== --- app/models/version.rb (revision 1680) +++ app/models/version.rb (working copy) @@ -26,6 +26,12 @@ validates_length_of :name, :maximum => 60 validates_format_of :effective_date, :with => /^\d{4}-\d{2}-\d{2}$/, :message => :activerecord_error_not_a_date, :allow_nil => true + def validate + if completed? && open_issues_count > 0 + errors.add :completed, :activerecord_error_open_issues + end + end + def start_date effective_date end @@ -44,11 +50,6 @@ @spent_hours ||= TimeEntry.sum(:hours, :include => :issue, :conditions => ["#{Issue.table_name}.fixed_version_id = ?", id]).to_f end - # Returns true if the version is completed: due date reached and no open issues - def completed? - effective_date && (effective_date <= Date.today) && (open_issues_count == 0) - end - def completed_pourcent if fixed_issues.count == 0 0 @@ -69,7 +70,7 @@ # Returns true if the version is overdue: due date reached and some open issues def overdue? - effective_date && (effective_date < Date.today) && (open_issues_count > 0) + effective_date && (effective_date < Date.today) && (!self.completed?) end def open_issues_count Index: app/models/project.rb =================================================================== --- app/models/project.rb (revision 1680) +++ app/models/project.rb (working copy) @@ -171,6 +171,10 @@ children.select {|child| child.active?} end + def incomplete_versions + versions.reject(&:completed?).sort + end + # Returns an array of the trackers used by the project and its sub projects def rolled_up_trackers @rolled_up_trackers ||= Index: app/controllers/issues_controller.rb =================================================================== --- app/controllers/issues_controller.rb (revision 1680) +++ app/controllers/issues_controller.rb (working copy) @@ -99,6 +99,7 @@ @journals.each_with_index {|j,i| j.indice = i+1} @journals.reverse! if User.current.wants_comments_in_reverse_order? @allowed_statuses = @issue.new_statuses_allowed_to(User.current) + @targetable_versions = ([@issue.fixed_version] + @project.incomplete_versions).compact.uniq.sort @edit_allowed = User.current.allowed_to?(:edit_issues, @project) @priorities = Enumeration::get_values('IPRI') @time_entry = TimeEntry.new @@ -133,6 +134,7 @@ end @issue.status = default_status @allowed_statuses = ([default_status] + default_status.find_new_statuses_allowed_to(User.current.role_for_project(@project), @issue.tracker)).uniq + @targetable_versions = ([@issue.fixed_version] + @project.incomplete_versions).compact.uniq.sort if request.get? || request.xhr? @issue.start_date ||= Date.today @@ -158,6 +160,7 @@ def edit @allowed_statuses = @issue.new_statuses_allowed_to(User.current) + @targetable_versions = ([@issue.fixed_version] + @project.incomplete_versions).compact.uniq.sort @priorities = Enumeration::get_values('IPRI') @edit_allowed = User.current.allowed_to?(:edit_issues, @project) @@ -323,15 +326,17 @@ def context_menu @issues = Issue.find_all_by_id(params[:ids], :include => :project) + projects = @issues.collect(&:project).compact.uniq + @project = projects.first if projects.size == 1 + if (@issues.size == 1) @issue = @issues.first @allowed_statuses = @issue.new_statuses_allowed_to(User.current) @assignables = @issue.assignable_users @assignables << @issue.assigned_to if @issue.assigned_to && !@assignables.include?(@issue.assigned_to) + @targetable_versions = ([@issue.fixed_version] + @project.incomplete_versions).compact.uniq.sort end - projects = @issues.collect(&:project).compact.uniq - @project = projects.first if projects.size == 1 - + @can = {:edit => (@project && User.current.allowed_to?(:edit_issues, @project)), :log_time => (@project && User.current.allowed_to?(:log_time, @project)), :update => (@issue && (User.current.allowed_to?(:edit_issues, @project) || (User.current.allowed_to?(:change_status, @project) && !@allowed_statuses.empty?))), Index: app/controllers/projects_controller.rb =================================================================== --- app/controllers/projects_controller.rb (revision 1680) +++ app/controllers/projects_controller.rb (working copy) @@ -213,8 +213,7 @@ def roadmap @trackers = @project.trackers.find(:all, :conditions => ["is_in_roadmap=?", true]) retrieve_selected_tracker_ids(@trackers) - @versions = @project.versions.sort - @versions = @versions.select {|v| !v.completed? } unless params[:completed] + @versions = params[:completed] ? @project.versions.sort : @project.incomplete_versions end def activity Index: app/views/versions/_form.rhtml =================================================================== --- app/views/versions/_form.rhtml (revision 1680) +++ app/views/versions/_form.rhtml (working copy) @@ -5,4 +5,5 @@
<%= f.text_field :description, :size => 60 %>
<%= f.text_field :wiki_page_title, :label => :label_wiki_page, :size => 60, :disabled => @project.wiki.nil? %>
<%= f.text_field :effective_date, :size => 10 %><%= calendar_for('version_effective_date') %>
+<%= f.check_box :completed, :label => :label_completed_version %> Index: app/views/issues/_form.rhtml =================================================================== --- app/views/issues/_form.rhtml (revision 1680) +++ app/views/issues/_form.rhtml (working copy) @@ -30,8 +30,8 @@ {:controller => 'projects', :action => 'add_issue_category', :id => @project}, :class => 'small', :tabindex => 199) if authorize_for('projects', 'add_issue_category') %>
<%= content_tag('p', f.select(:fixed_version_id, - (@project.versions.sort.collect {|v| [v.name, v.id]}), - { :include_blank => true })) unless @project.versions.empty? %> + (@targetable_versions.collect {|v| [v.name, v.id]}), + { :include_blank => true })) unless @targetable_versions.empty? %>Index: app/views/issues/_form_update.rhtml =================================================================== --- app/views/issues/_form_update.rhtml (revision 1680) +++ app/views/issues/_form_update.rhtml (working copy) @@ -5,6 +5,6 @@
<%= f.select :done_ratio, ((0..10).to_a.collect {|r| ["#{r*10} %", r*10] }) %>
<%= content_tag('p', f.select(:fixed_version_id, - (@project.versions.sort.collect {|v| [v.name, v.id]}), - { :include_blank => true })) unless @project.versions.empty? %> + (@targetable_versions.collect {|v| [v.name, v.id]}), + { :include_blank => true })) unless @targetable_versions.empty? %>