diff --git a/app/models/issue.rb b/app/models/issue.rb index 4e32dce..0f0fd62 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -73,7 +73,7 @@ class Issue < ActiveRecord::Base validates :estimated_hours, :numericality => {:greater_than_or_equal_to => 0, :allow_nil => true, :message => :invalid} validates :start_date, :date => true validates :due_date, :date => true - validate :validate_issue, :validate_required_fields + validate :validate_issue, :validate_required_fields, :validate_subtasks attr_protected :id scope :visible, lambda {|*args| @@ -757,6 +757,13 @@ class Issue < ActiveRecord::Base end end + # Validates the issue against open subtasks + def validate_subtasks + if closing? && descendants.open.any? + errors.add :base, I18n.t(:error_can_not_close_issue_with_open_subtasks) + end + end + # Set the done_ratio using the status if that setting is set. This will keep the done_ratios # even if the user turns off the setting later def update_done_ratio_from_issue_status diff --git a/config/locales/en.yml b/config/locales/en.yml index 56a06c7..38ccbd1 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -215,6 +215,7 @@ en: error_ldap_bind_credentials: "Invalid LDAP Account/Password" error_no_tracker_allowed_for_new_issue_in_project: "The project doesn't have any trackers for which you can create an issue" error_no_projects_with_tracker_allowed_for_new_issue: "There are no projects with trackers for which you can create an issue" + error_can_not_close_issue_with_open_subtasks: "An issue with open subtasks cannot be closed" mail_subject_lost_password: "Your %{value} password" mail_body_lost_password: 'To change your password, click on the following link:' diff --git a/test/unit/issue_subtasking_test.rb b/test/unit/issue_subtasking_test.rb index 020bcfd..dc72e30 100644 --- a/test/unit/issue_subtasking_test.rb +++ b/test/unit/issue_subtasking_test.rb @@ -306,4 +306,25 @@ class IssueSubtaskingTest < ActiveSupport::TestCase parent.generate_child!(:estimated_hours => 7) assert_equal 12, parent.reload.total_estimated_hours end + + def test_parent_with_open_subtasks_cannot_be_closed + parent = Issue.generate! + parent.generate_child!() + parent.reload + parent.status = IssueStatus.where(:is_closed => true).first + parent.save + + assert_include 'An issue with open subtasks cannot be closed', parent.errors.full_messages + end + + def test_parent_with_closed_subtasks_can_be_closed + parent = Issue.generate! + parent.generate_child!(:status => IssueStatus.where(:is_closed => true).first) + parent.reload + closed_status = IssueStatus.where(:is_closed => true).first + parent.status = closed_status + + assert_save parent + assert parent.status, closed_status + end end