Index: trunk/app/models/issue.rb
===================================================================
--- trunk/app/models/issue.rb	(revision 3019)
+++ trunk/app/models/issue.rb	(revision 3020)
@@ -143,6 +143,14 @@
     if start_date && soonest_start && start_date < soonest_start
       errors.add :start_date, :invalid
     end
+    
+    if fixed_version
+      if !assignable_versions.include?(fixed_version)
+        errors.add :fixed_version_id, :inclusion
+      elsif reopened? && fixed_version.closed?
+        errors.add_to_base I18n.t(:error_can_not_reopen_issue_on_closed_version)
+      end
+    end
   end
   
   def validate_on_create
@@ -193,6 +201,18 @@
     self.status.is_closed?
   end
   
+  # Return true if the issue is being reopened
+  def reopened?
+    if !new_record? && status_id_changed?
+      status_was = IssueStatus.find_by_id(status_id_was)
+      status_new = IssueStatus.find_by_id(status_id)
+      if status_was && status_new && status_was.is_closed? && !status_new.is_closed?
+        return true
+      end
+    end
+    false
+  end
+  
   # Returns true if the issue is overdue
   def overdue?
     !due_date.nil? && (due_date < Date.today) && !status.is_closed?
@@ -203,6 +223,11 @@
     project.assignable_users
   end
   
+  # Versions that the issue can be assigned to
+  def assignable_versions
+    @assignable_versions ||= (project.versions.open + [Version.find_by_id(fixed_version_id_was)]).compact.uniq.sort
+  end
+  
   # Returns true if this issue is blocked by another issue that is still open
   def blocked?
     !relations_to.detect {|ir| ir.relation_type == 'blocks' && !ir.issue_from.closed?}.nil?
Index: trunk/app/models/version.rb
===================================================================
--- trunk/app/models/version.rb	(revision 3019)
+++ trunk/app/models/version.rb	(revision 3020)
@@ -22,11 +22,16 @@
   acts_as_attachable :view_permission => :view_files,
                      :delete_permission => :manage_files
 
+  VERSION_STATUSES = %w(open locked closed)
+  
   validates_presence_of :name
   validates_uniqueness_of :name, :scope => [:project_id]
   validates_length_of :name, :maximum => 60
   validates_format_of :effective_date, :with => /^\d{4}-\d{2}-\d{2}$/, :message => :not_a_date, :allow_nil => true
-  
+  validates_inclusion_of :status, :in => VERSION_STATUSES
+
+  named_scope :open, :conditions => {:status => 'open'}
+    
   def start_date
     effective_date
   end
@@ -45,6 +50,10 @@
     @spent_hours ||= TimeEntry.sum(:hours, :include => :issue, :conditions => ["#{Issue.table_name}.fixed_version_id = ?", id]).to_f
   end
   
+  def closed?
+    status == 'closed'
+  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)
Index: trunk/app/views/issues/_form.rhtml
===================================================================
--- trunk/app/views/issues/_form.rhtml	(revision 3019)
+++ trunk/app/views/issues/_form.rhtml	(revision 3020)
@@ -32,9 +32,9 @@
                      {:controller => 'projects', :action => 'add_issue_category', :id => @project},
                      :class => 'small', :tabindex => 199) if authorize_for('projects', 'add_issue_category') %></p>
 <% end %>
-<%= content_tag('p', f.select(:fixed_version_id, 
-                              (@project.versions.sort.collect {|v| [v.name, v.id]}),
-                              { :include_blank => true })) unless @project.versions.empty? %>
+<% unless @issue.assignable_versions.empty? %>
+<p><%= f.select :fixed_version_id, (@issue.assignable_versions.collect {|v| [v.name, v.id]}), :include_blank => true %></p>
+<% end %>
 </div>
 
 <div class="splitcontentright">
Index: trunk/app/views/issues/_form_update.rhtml
===================================================================
--- trunk/app/views/issues/_form_update.rhtml	(revision 3019)
+++ trunk/app/views/issues/_form_update.rhtml	(revision 3020)
@@ -5,8 +5,8 @@
 </div>
 <div class="splitcontentright">
 <p><%= f.select :done_ratio, ((0..10).to_a.collect {|r| ["#{r*10} %", r*10] }) %></p>
-<%= content_tag('p', f.select(:fixed_version_id, 
-                          (@project.versions.sort.collect {|v| [v.name, v.id]}),
-                          { :include_blank => true })) unless @project.versions.empty? %>
+<% unless @issue.assignable_versions.empty? %>
+<p><%= f.select :fixed_version_id, (@issue.assignable_versions.collect {|v| [v.name, v.id]}), :include_blank => true %></p>
+<% end %>
 </div>
 </div>
Index: trunk/app/views/issues/bulk_edit.rhtml
===================================================================
--- trunk/app/views/issues/bulk_edit.rhtml	(revision 3019)
+++ trunk/app/views/issues/bulk_edit.rhtml	(revision 3020)
@@ -27,7 +27,7 @@
 <label><%= l(:field_fixed_version) %>: 
 <%= select_tag('fixed_version_id', content_tag('option', l(:label_no_change_option), :value => '') +
                                    content_tag('option', l(:label_none), :value => 'none') +
-                                   options_from_collection_for_select(@project.versions.sort, :id, :name)) %></label>
+                                   options_from_collection_for_select(@project.versions.open.sort, :id, :name)) %></label>
 </p>
 
 <p>
Index: trunk/app/views/issues/context_menu.rhtml
===================================================================
--- trunk/app/views/issues/context_menu.rhtml	(revision 3019)
+++ trunk/app/views/issues/context_menu.rhtml	(revision 3020)
@@ -27,11 +27,11 @@
 		<% end -%>
 		</ul>
 	</li>
-	<% unless @project.nil? || @project.versions.empty? -%>
+	<% unless @project.nil? || @project.versions.open.empty? -%>
 	<li class="folder">			
 		<a href="#" class="submenu"><%= l(:field_fixed_version) %></a>
 		<ul>
-		<% @project.versions.sort.each do |v| -%>
+		<% @project.versions.open.sort.each do |v| -%>
 		    <li><%= context_menu_link v.name, {:controller => 'issues', :action => 'bulk_edit', :ids => @issues.collect(&:id), 'fixed_version_id' => v, :back_to => @back}, :method => :post,
 		                              :selected => (@issue && v == @issue.fixed_version), :disabled => !@can[:update] %></li>
 		<% end -%>
Index: trunk/app/views/projects/settings/_versions.rhtml
===================================================================
--- trunk/app/views/projects/settings/_versions.rhtml	(revision 3019)
+++ trunk/app/views/projects/settings/_versions.rhtml	(revision 3020)
@@ -1,22 +1,25 @@
 <% if @project.versions.any? %>
-<table class="list">
+<table class="list versions">
 	<thead>
     <th><%= l(:label_version) %></th>
     <th><%= l(:field_effective_date) %></th>
     <th><%= l(:field_description) %></th>
+    <th><%= l(:field_status) %></th>
     <th><%= l(:label_wiki_page) unless @project.wiki.nil? %></th>
     <th style="width:15%"></th>
-    <th style="width:15%"></th>
     </thead>
 	<tbody>
 <% for version in @project.versions.sort %>
-    <tr class="<%= cycle 'odd', 'even' %>">
+    <tr class="version <%= cycle 'odd', 'even' %> <%=h version.status %>">
     <td><%= link_to h(version.name), :controller => 'versions', :action => 'show', :id => version %></td>
     <td align="center"><%= format_date(version.effective_date) %></td>
     <td><%=h version.description %></td>
+    <td><%= l("version_status_#{version.status}") %></td>
     <td><%= link_to(h(version.wiki_page_title), :controller => 'wiki', :page => Wiki.titleize(version.wiki_page_title)) unless version.wiki_page_title.blank? || @project.wiki.nil? %></td>
-    <td align="center"><%= link_to_if_authorized l(:button_edit), { :controller => 'versions', :action => 'edit', :id => version }, :class => 'icon icon-edit' %></td>
-    <td align="center"><%= link_to_if_authorized l(:button_delete), {:controller => 'versions', :action => 'destroy', :id => version}, :confirm => l(:text_are_you_sure), :method => :post, :class => 'icon icon-del' %></td>
+    <td class="buttons">
+    	<%= link_to_if_authorized l(:button_edit),   {:controller => 'versions', :action => 'edit', :id => version }, :class => 'icon icon-edit' %>
+    	<%= link_to_if_authorized l(:button_delete), {:controller => 'versions', :action => 'destroy', :id => version}, :confirm => l(:text_are_you_sure), :method => :post, :class => 'icon icon-del' %>
+   	</td>
     </tr>
 <% end; reset_cycle %>
     </tbody>
Index: trunk/app/views/versions/_form.rhtml
===================================================================
--- trunk/app/views/versions/_form.rhtml	(revision 3019)
+++ trunk/app/views/versions/_form.rhtml	(revision 3020)
@@ -3,6 +3,7 @@
 <div class="box">
 <p><%= f.text_field :name, :size => 60, :required => true %></p>
 <p><%= f.text_field :description, :size => 60 %></p>
+<p><%= f.select :status, Version::VERSION_STATUSES.collect {|s| [l("version_status_#{s}"), s]} %></p>
 <p><%= f.text_field :wiki_page_title, :label => :label_wiki_page, :size => 60, :disabled => @project.wiki.nil? %></p>
 <p><%= f.text_field :effective_date, :size => 10 %><%= calendar_for('version_effective_date') %></p>
 </div>
Index: trunk/config/locales/bg.yml
===================================================================
--- trunk/config/locales/bg.yml	(revision 3019)
+++ trunk/config/locales/bg.yml	(revision 3020)
@@ -827,3 +827,7 @@
   field_active: Active
   enumeration_system_activity: System Activity
   permission_delete_issue_watchers: Delete watchers
+  version_status_closed: closed
+  version_status_locked: locked
+  version_status_open: open
+  error_can_not_reopen_issue_on_closed_version: An issue assigned to a closed version can not be reopened
Index: trunk/config/locales/bs.yml
===================================================================
--- trunk/config/locales/bs.yml	(revision 3019)
+++ trunk/config/locales/bs.yml	(revision 3020)
@@ -851,3 +851,7 @@
   field_active: Active
   enumeration_system_activity: System Activity
   permission_delete_issue_watchers: Delete watchers
+  version_status_closed: closed
+  version_status_locked: locked
+  version_status_open: open
+  error_can_not_reopen_issue_on_closed_version: An issue assigned to a closed version can not be reopened
Index: trunk/config/locales/ca.yml
===================================================================
--- trunk/config/locales/ca.yml	(revision 3019)
+++ trunk/config/locales/ca.yml	(revision 3020)
@@ -830,3 +830,7 @@
   field_active: Active
   enumeration_system_activity: System Activity
   permission_delete_issue_watchers: Delete watchers
+  version_status_closed: closed
+  version_status_locked: locked
+  version_status_open: open
+  error_can_not_reopen_issue_on_closed_version: An issue assigned to a closed version can not be reopened
Index: trunk/config/locales/cs.yml
===================================================================
--- trunk/config/locales/cs.yml	(revision 3019)
+++ trunk/config/locales/cs.yml	(revision 3020)
@@ -833,3 +833,7 @@
   field_active: Active
   enumeration_system_activity: System Activity
   permission_delete_issue_watchers: Delete watchers
+  version_status_closed: closed
+  version_status_locked: locked
+  version_status_open: open
+  error_can_not_reopen_issue_on_closed_version: An issue assigned to a closed version can not be reopened
Index: trunk/config/locales/da.yml
===================================================================
--- trunk/config/locales/da.yml	(revision 3019)
+++ trunk/config/locales/da.yml	(revision 3020)
@@ -853,3 +853,7 @@
   field_active: Active
   enumeration_system_activity: System Activity
   permission_delete_issue_watchers: Delete watchers
+  version_status_closed: closed
+  version_status_locked: locked
+  version_status_open: open
+  error_can_not_reopen_issue_on_closed_version: An issue assigned to a closed version can not be reopened
Index: trunk/config/locales/de.yml
===================================================================
--- trunk/config/locales/de.yml	(revision 3019)
+++ trunk/config/locales/de.yml	(revision 3020)
@@ -853,3 +853,7 @@
   field_active: Active
   enumeration_system_activity: System Activity
   permission_delete_issue_watchers: Delete watchers
+  version_status_closed: closed
+  version_status_locked: locked
+  version_status_open: open
+  error_can_not_reopen_issue_on_closed_version: An issue assigned to a closed version can not be reopened
Index: trunk/config/locales/el.yml
===================================================================
--- trunk/config/locales/el.yml	(revision 3019)
+++ trunk/config/locales/el.yml	(revision 3020)
@@ -833,3 +833,7 @@
   field_active: Active
   enumeration_system_activity: System Activity
   permission_delete_issue_watchers: Delete watchers
+  version_status_closed: closed
+  version_status_locked: locked
+  version_status_open: open
+  error_can_not_reopen_issue_on_closed_version: An issue assigned to a closed version can not be reopened
Index: trunk/config/locales/en.yml
===================================================================
--- trunk/config/locales/en.yml	(revision 3019)
+++ trunk/config/locales/en.yml	(revision 3020)
@@ -155,6 +155,7 @@
   error_issue_not_found_in_project: 'The issue was not found or does not belong to this project'
   error_no_tracker_in_project: 'No tracker is associated to this project. Please check the Project settings.'
   error_no_default_issue_status: 'No default issue status is defined. Please check your configuration (Go to "Administration -> Issue statuses").'
+  error_can_not_reopen_issue_on_closed_version: 'An issue assigned to a closed version can not be reopened'
   
   warning_attachments_not_saved: "{{count}} file(s) could not be saved."
   
@@ -749,6 +750,10 @@
   status_active: active
   status_registered: registered
   status_locked: locked
+  
+  version_status_open: open
+  version_status_locked: locked
+  version_status_closed: closed
 
   field_active: Active
   
Index: trunk/config/locales/es.yml
===================================================================
--- trunk/config/locales/es.yml	(revision 3019)
+++ trunk/config/locales/es.yml	(revision 3020)
@@ -874,3 +874,7 @@
   field_active: Active
   enumeration_system_activity: System Activity
   permission_delete_issue_watchers: Delete watchers
+  version_status_closed: closed
+  version_status_locked: locked
+  version_status_open: open
+  error_can_not_reopen_issue_on_closed_version: An issue assigned to a closed version can not be reopened
Index: trunk/config/locales/fi.yml
===================================================================
--- trunk/config/locales/fi.yml	(revision 3019)
+++ trunk/config/locales/fi.yml	(revision 3020)
@@ -863,3 +863,7 @@
   field_active: Active
   enumeration_system_activity: System Activity
   permission_delete_issue_watchers: Delete watchers
+  version_status_closed: closed
+  version_status_locked: locked
+  version_status_open: open
+  error_can_not_reopen_issue_on_closed_version: An issue assigned to a closed version can not be reopened
Index: trunk/config/locales/fr.yml
===================================================================
--- trunk/config/locales/fr.yml	(revision 3019)
+++ trunk/config/locales/fr.yml	(revision 3020)
@@ -177,6 +177,7 @@
   error_scm_command_failed: "Une erreur s'est produite lors de l'accès au dépôt: {{value}}"
   error_scm_annotate: "L'entrée n'existe pas ou ne peut pas être annotée."
   error_issue_not_found_in_project: "La demande n'existe pas ou n'appartient pas à ce projet"
+  error_can_not_reopen_issue_on_closed_version: 'Une demande assignée à une version fermée ne peut pas être réouverte'
   
   warning_attachments_not_saved: "{{count}} fichier(s) n'ont pas pu être sauvegardés."
   
@@ -767,6 +768,10 @@
   status_registered: enregistré
   status_locked: vérouillé
   
+  version_status_open: ouvert
+  version_status_locked: vérouillé
+  version_status_closed: fermé
+  
   text_select_mail_notifications: Actions pour lesquelles une notification par e-mail est envoyée
   text_regexp_info: ex. ^[A-Z0-9]+$
   text_min_max_length_info: 0 pour aucune restriction
Index: trunk/config/locales/gl.yml
===================================================================
--- trunk/config/locales/gl.yml	(revision 3019)
+++ trunk/config/locales/gl.yml	(revision 3020)
@@ -853,3 +853,7 @@
   field_active: Active
   enumeration_system_activity: System Activity
   permission_delete_issue_watchers: Delete watchers
+  version_status_closed: closed
+  version_status_locked: locked
+  version_status_open: open
+  error_can_not_reopen_issue_on_closed_version: An issue assigned to a closed version can not be reopened
Index: trunk/config/locales/he.yml
===================================================================
--- trunk/config/locales/he.yml	(revision 3019)
+++ trunk/config/locales/he.yml	(revision 3020)
@@ -837,3 +837,7 @@
   field_active: Active
   enumeration_system_activity: System Activity
   permission_delete_issue_watchers: Delete watchers
+  version_status_closed: closed
+  version_status_locked: locked
+  version_status_open: open
+  error_can_not_reopen_issue_on_closed_version: An issue assigned to a closed version can not be reopened
Index: trunk/config/locales/hu.yml
===================================================================
--- trunk/config/locales/hu.yml	(revision 3019)
+++ trunk/config/locales/hu.yml	(revision 3020)
@@ -858,3 +858,7 @@
   field_active: Active
   enumeration_system_activity: System Activity
   permission_delete_issue_watchers: Delete watchers
+  version_status_closed: closed
+  version_status_locked: locked
+  version_status_open: open
+  error_can_not_reopen_issue_on_closed_version: An issue assigned to a closed version can not be reopened
Index: trunk/config/locales/it.yml
===================================================================
--- trunk/config/locales/it.yml	(revision 3019)
+++ trunk/config/locales/it.yml	(revision 3020)
@@ -840,3 +840,7 @@
   field_active: Active
   enumeration_system_activity: System Activity
   permission_delete_issue_watchers: Delete watchers
+  version_status_closed: closed
+  version_status_locked: locked
+  version_status_open: open
+  error_can_not_reopen_issue_on_closed_version: An issue assigned to a closed version can not be reopened
Index: trunk/config/locales/ja.yml
===================================================================
--- trunk/config/locales/ja.yml	(revision 3019)
+++ trunk/config/locales/ja.yml	(revision 3020)
@@ -862,3 +862,7 @@
   field_active: Active
   enumeration_system_activity: System Activity
   permission_delete_issue_watchers: Delete watchers
+  version_status_closed: closed
+  version_status_locked: locked
+  version_status_open: open
+  error_can_not_reopen_issue_on_closed_version: An issue assigned to a closed version can not be reopened
Index: trunk/config/locales/ko.yml
===================================================================
--- trunk/config/locales/ko.yml	(revision 3019)
+++ trunk/config/locales/ko.yml	(revision 3020)
@@ -893,3 +893,7 @@
   field_active: Active
   enumeration_system_activity: System Activity
   permission_delete_issue_watchers: Delete watchers
+  version_status_closed: closed
+  version_status_locked: locked
+  version_status_open: open
+  error_can_not_reopen_issue_on_closed_version: An issue assigned to a closed version can not be reopened
Index: trunk/config/locales/lt.yml
===================================================================
--- trunk/config/locales/lt.yml	(revision 3019)
+++ trunk/config/locales/lt.yml	(revision 3020)
@@ -863,3 +863,7 @@
   field_active: Active
   enumeration_system_activity: System Activity
   permission_delete_issue_watchers: Delete watchers
+  version_status_closed: closed
+  version_status_locked: locked
+  version_status_open: open
+  error_can_not_reopen_issue_on_closed_version: An issue assigned to a closed version can not be reopened
Index: trunk/config/locales/nl.yml
===================================================================
--- trunk/config/locales/nl.yml	(revision 3019)
+++ trunk/config/locales/nl.yml	(revision 3020)
@@ -815,3 +815,7 @@
   field_active: Active
   enumeration_system_activity: System Activity
   permission_delete_issue_watchers: Delete watchers
+  version_status_closed: closed
+  version_status_locked: locked
+  version_status_open: open
+  error_can_not_reopen_issue_on_closed_version: An issue assigned to a closed version can not be reopened
Index: trunk/config/locales/no.yml
===================================================================
--- trunk/config/locales/no.yml	(revision 3019)
+++ trunk/config/locales/no.yml	(revision 3020)
@@ -828,3 +828,7 @@
   field_active: Active
   enumeration_system_activity: System Activity
   permission_delete_issue_watchers: Delete watchers
+  version_status_closed: closed
+  version_status_locked: locked
+  version_status_open: open
+  error_can_not_reopen_issue_on_closed_version: An issue assigned to a closed version can not be reopened
Index: trunk/config/locales/pl.yml
===================================================================
--- trunk/config/locales/pl.yml	(revision 3019)
+++ trunk/config/locales/pl.yml	(revision 3020)
@@ -856,3 +856,7 @@
   field_active: Aktywne
   enumeration_system_activity: Aktywność Systemowa
   permission_delete_issue_watchers: Delete watchers
+  version_status_closed: closed
+  version_status_locked: locked
+  version_status_open: open
+  error_can_not_reopen_issue_on_closed_version: An issue assigned to a closed version can not be reopened
Index: trunk/config/locales/pt-BR.yml
===================================================================
--- trunk/config/locales/pt-BR.yml	(revision 3019)
+++ trunk/config/locales/pt-BR.yml	(revision 3020)
@@ -859,3 +859,7 @@
   field_active: Ativo
   enumeration_system_activity: Atividade do sistema
   permission_delete_issue_watchers: Deletar observadores
+  version_status_closed: closed
+  version_status_locked: locked
+  version_status_open: open
+  error_can_not_reopen_issue_on_closed_version: An issue assigned to a closed version can not be reopened
Index: trunk/config/locales/pt.yml
===================================================================
--- trunk/config/locales/pt.yml	(revision 3019)
+++ trunk/config/locales/pt.yml	(revision 3020)
@@ -845,3 +845,7 @@
   field_active: Active
   enumeration_system_activity: System Activity
   permission_delete_issue_watchers: Delete watchers
+  version_status_closed: closed
+  version_status_locked: locked
+  version_status_open: open
+  error_can_not_reopen_issue_on_closed_version: An issue assigned to a closed version can not be reopened
Index: trunk/config/locales/ro.yml
===================================================================
--- trunk/config/locales/ro.yml	(revision 3019)
+++ trunk/config/locales/ro.yml	(revision 3020)
@@ -830,3 +830,7 @@
   field_active: Active
   enumeration_system_activity: System Activity
   permission_delete_issue_watchers: Delete watchers
+  version_status_closed: closed
+  version_status_locked: locked
+  version_status_open: open
+  error_can_not_reopen_issue_on_closed_version: An issue assigned to a closed version can not be reopened
Index: trunk/config/locales/ru.yml
===================================================================
--- trunk/config/locales/ru.yml	(revision 3019)
+++ trunk/config/locales/ru.yml	(revision 3020)
@@ -941,3 +941,7 @@
   field_active: Active
   enumeration_system_activity: System Activity
   permission_delete_issue_watchers: Delete watchers
+  version_status_closed: closed
+  version_status_locked: locked
+  version_status_open: open
+  error_can_not_reopen_issue_on_closed_version: An issue assigned to a closed version can not be reopened
Index: trunk/config/locales/sk.yml
===================================================================
--- trunk/config/locales/sk.yml	(revision 3019)
+++ trunk/config/locales/sk.yml	(revision 3020)
@@ -832,3 +832,7 @@
   field_active: Active
   enumeration_system_activity: System Activity
   permission_delete_issue_watchers: Delete watchers
+  version_status_closed: closed
+  version_status_locked: locked
+  version_status_open: open
+  error_can_not_reopen_issue_on_closed_version: An issue assigned to a closed version can not be reopened
Index: trunk/config/locales/sl.yml
===================================================================
--- trunk/config/locales/sl.yml	(revision 3019)
+++ trunk/config/locales/sl.yml	(revision 3020)
@@ -829,3 +829,7 @@
   field_active: Active
   enumeration_system_activity: System Activity
   permission_delete_issue_watchers: Delete watchers
+  version_status_closed: closed
+  version_status_locked: locked
+  version_status_open: open
+  error_can_not_reopen_issue_on_closed_version: An issue assigned to a closed version can not be reopened
Index: trunk/config/locales/sr.yml
===================================================================
--- trunk/config/locales/sr.yml	(revision 3019)
+++ trunk/config/locales/sr.yml	(revision 3020)
@@ -848,3 +848,7 @@
   field_active: Active
   enumeration_system_activity: System Activity
   permission_delete_issue_watchers: Delete watchers
+  version_status_closed: closed
+  version_status_locked: locked
+  version_status_open: open
+  error_can_not_reopen_issue_on_closed_version: An issue assigned to a closed version can not be reopened
Index: trunk/config/locales/sv.yml
===================================================================
--- trunk/config/locales/sv.yml	(revision 3019)
+++ trunk/config/locales/sv.yml	(revision 3020)
@@ -881,3 +881,7 @@
   enumeration_doc_categories: Dokumentkategorier
   enumeration_activities: Aktiviteter (tidsuppföljning)
   enumeration_system_activity: Systemaktivitet
+  version_status_closed: closed
+  version_status_locked: locked
+  version_status_open: open
+  error_can_not_reopen_issue_on_closed_version: An issue assigned to a closed version can not be reopened
Index: trunk/config/locales/th.yml
===================================================================
--- trunk/config/locales/th.yml	(revision 3019)
+++ trunk/config/locales/th.yml	(revision 3020)
@@ -830,3 +830,7 @@
   field_active: Active
   enumeration_system_activity: System Activity
   permission_delete_issue_watchers: Delete watchers
+  version_status_closed: closed
+  version_status_locked: locked
+  version_status_open: open
+  error_can_not_reopen_issue_on_closed_version: An issue assigned to a closed version can not be reopened
Index: trunk/config/locales/tr.yml
===================================================================
--- trunk/config/locales/tr.yml	(revision 3019)
+++ trunk/config/locales/tr.yml	(revision 3020)
@@ -860,3 +860,7 @@
   field_active: Active
   enumeration_system_activity: System Activity
   permission_delete_issue_watchers: Delete watchers
+  version_status_closed: closed
+  version_status_locked: locked
+  version_status_open: open
+  error_can_not_reopen_issue_on_closed_version: An issue assigned to a closed version can not be reopened
Index: trunk/config/locales/uk.yml
===================================================================
--- trunk/config/locales/uk.yml	(revision 3019)
+++ trunk/config/locales/uk.yml	(revision 3020)
@@ -829,3 +829,7 @@
   field_active: Active
   enumeration_system_activity: System Activity
   permission_delete_issue_watchers: Delete watchers
+  version_status_closed: closed
+  version_status_locked: locked
+  version_status_open: open
+  error_can_not_reopen_issue_on_closed_version: An issue assigned to a closed version can not be reopened
Index: trunk/config/locales/vi.yml
===================================================================
--- trunk/config/locales/vi.yml	(revision 3019)
+++ trunk/config/locales/vi.yml	(revision 3020)
@@ -892,3 +892,7 @@
   field_active: Active
   enumeration_system_activity: System Activity
   permission_delete_issue_watchers: Delete watchers
+  version_status_closed: closed
+  version_status_locked: locked
+  version_status_open: open
+  error_can_not_reopen_issue_on_closed_version: An issue assigned to a closed version can not be reopened
Index: trunk/config/locales/zh-TW.yml
===================================================================
--- trunk/config/locales/zh-TW.yml	(revision 3019)
+++ trunk/config/locales/zh-TW.yml	(revision 3020)
@@ -923,3 +923,7 @@
   enumeration_doc_categories: 文件分類
   enumeration_activities: 活動 (時間追蹤)
   enumeration_system_activity: 系統活動
+  version_status_closed: closed
+  version_status_locked: locked
+  version_status_open: open
+  error_can_not_reopen_issue_on_closed_version: An issue assigned to a closed version can not be reopened
Index: trunk/config/locales/zh.yml
===================================================================
--- trunk/config/locales/zh.yml	(revision 3019)
+++ trunk/config/locales/zh.yml	(revision 3020)
@@ -855,3 +855,7 @@
   field_active: Active
   enumeration_system_activity: System Activity
   permission_delete_issue_watchers: Delete watchers
+  version_status_closed: closed
+  version_status_locked: locked
+  version_status_open: open
+  error_can_not_reopen_issue_on_closed_version: An issue assigned to a closed version can not be reopened
Index: trunk/db/migrate/20091108092559_add_versions_status.rb
===================================================================
--- trunk/db/migrate/20091108092559_add_versions_status.rb	(nonexistent)
+++ trunk/db/migrate/20091108092559_add_versions_status.rb	(revision 3020)
@@ -0,0 +1,9 @@
+class AddVersionsStatus < ActiveRecord::Migration
+  def self.up
+    add_column :versions, :status, :string, :default => 'open'
+  end
+
+  def self.down
+    remove_column :versions, :status
+  end
+end

Property changes on: trunk/db/migrate/20091108092559_add_versions_status.rb
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: trunk/public/stylesheets/application.css
===================================================================
--- trunk/public/stylesheets/application.css	(revision 3019)
+++ trunk/public/stylesheets/application.css	(revision 3020)
@@ -124,6 +124,8 @@
 tr.message.locked td.subject a { background-image: url(../images/locked.png); }
 tr.message.sticky td.subject a { background-image: url(../images/sticky.png); font-weight: bold; }
 
+tr.version.closed, tr.version.closed a { color: #999; }
+
 tr.user td { width:13%; }
 tr.user td.email { width:18%; }
 tr.user td { white-space: nowrap; }
Index: trunk/test/fixtures/issues.yml
===================================================================
--- trunk/test/fixtures/issues.yml	(revision 3019)
+++ trunk/test/fixtures/issues.yml	(revision 3020)
@@ -157,3 +157,35 @@
   status_id: 1
   start_date: <%= Date.today.to_s(:db) %>
   due_date: <%= 1.days.from_now.to_date.to_s(:db) %>
+issues_011: 
+  created_on: <%= 3.days.ago.to_date.to_s(:db) %>
+  project_id: 1
+  updated_on: <%= 1.day.ago.to_date.to_s(:db) %>
+  priority_id: 5
+  subject: Closed issue on a closed version
+  id: 11
+  fixed_version_id: 1 
+  category_id: 1
+  description:
+  tracker_id: 1
+  assigned_to_id: 
+  author_id: 2
+  status_id: 5
+  start_date: <%= 1.day.ago.to_date.to_s(:db) %>
+  due_date:
+issues_012: 
+  created_on: <%= 3.days.ago.to_date.to_s(:db) %>
+  project_id: 1
+  updated_on: <%= 1.day.ago.to_date.to_s(:db) %>
+  priority_id: 5
+  subject: Closed issue on a locked version
+  id: 12
+  fixed_version_id: 2 
+  category_id: 1
+  description:
+  tracker_id: 1
+  assigned_to_id: 
+  author_id: 2
+  status_id: 5
+  start_date: <%= 1.day.ago.to_date.to_s(:db) %>
+  due_date:
Index: trunk/test/fixtures/versions.yml
===================================================================
--- trunk/test/fixtures/versions.yml	(revision 3019)
+++ trunk/test/fixtures/versions.yml	(revision 3020)
@@ -7,6 +7,7 @@
   id: 1
   description: Beta
   effective_date: 2006-07-01
+  status: closed
 versions_002: 
   created_on: 2006-07-19 21:00:33 +02:00
   name: "1.0"
@@ -15,6 +16,7 @@
   id: 2
   description: Stable release
   effective_date: <%= 20.day.from_now.to_date.to_s(:db) %>
+  status: locked
 versions_003: 
   created_on: 2006-07-19 21:00:33 +02:00
   name: "2.0"
@@ -23,4 +25,5 @@
   id: 3
   description: Future version
   effective_date: 
+  status: open
   
\ No newline at end of file
Index: trunk/test/unit/issue_test.rb
===================================================================
--- trunk/test/unit/issue_test.rb	(revision 3019)
+++ trunk/test/unit/issue_test.rb	(revision 3020)
@@ -20,6 +20,7 @@
 class IssueTest < ActiveSupport::TestCase
   fixtures :projects, :users, :members, :member_roles,
            :trackers, :projects_trackers,
+           :versions,
            :issue_statuses, :issue_categories, :issue_relations, :workflows, 
            :enumerations,
            :issues,
@@ -184,6 +185,56 @@
     assert !issue1.reload.closed?
   end
   
+  def test_assignable_versions
+    issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 1, :subject => 'New issue')
+    assert_equal ['open'], issue.assignable_versions.collect(&:status).uniq
+  end
+  
+  def test_should_not_be_able_to_assign_a_new_issue_to_a_closed_version
+    issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 1, :subject => 'New issue')
+    assert !issue.save
+    assert_not_nil issue.errors.on(:fixed_version_id)
+  end
+  
+  def test_should_not_be_able_to_assign_a_new_issue_to_a_locked_version
+    issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 2, :subject => 'New issue')
+    assert !issue.save
+    assert_not_nil issue.errors.on(:fixed_version_id)
+  end
+  
+  def test_should_be_able_to_assign_a_new_issue_to_an_open_version
+    issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 3, :subject => 'New issue')
+    assert issue.save
+  end
+  
+  def test_should_be_able_to_update_an_issue_assigned_to_a_closed_version
+    issue = Issue.find(11)
+    assert_equal 'closed', issue.fixed_version.status
+    issue.subject = 'Subject changed'
+    assert issue.save
+  end
+  
+  def test_should_not_be_able_to_reopen_an_issue_assigned_to_a_closed_version
+    issue = Issue.find(11)
+    issue.status_id = 1
+    assert !issue.save
+    assert_not_nil issue.errors.on_base
+  end
+  
+  def test_should_be_able_to_reopen_and_reassign_an_issue_assigned_to_a_closed_version
+    issue = Issue.find(11)
+    issue.status_id = 1
+    issue.fixed_version_id = 3
+    assert issue.save
+  end
+  
+  def test_should_be_able_to_reopen_an_issue_assigned_to_a_locked_version
+    issue = Issue.find(12)
+    assert_equal 'locked', issue.fixed_version.status
+    issue.status_id = 1
+    assert issue.save
+  end
+  
   def test_move_to_another_project_with_same_category
     issue = Issue.find(1)
     assert issue.move_to(Project.find(2))
Index: trunk/test/unit/version_test.rb
===================================================================
--- trunk/test/unit/version_test.rb	(revision 3019)
+++ trunk/test/unit/version_test.rb	(revision 3020)
@@ -26,6 +26,7 @@
   def test_create
     v = Version.new(:project => Project.find(1), :name => '1.1', :effective_date => '2011-03-25')
     assert v.save
+    assert_equal 'open', v.status
   end
   
   def test_invalid_effective_date_validation
