diff --git a/app/models/issue.rb b/app/models/issue.rb index 861d898e0..578f01ee7 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -203,11 +203,17 @@ class Issue < ActiveRecord::Base project.assignable_users 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? + end + # Returns an array of status that user is able to apply def new_statuses_allowed_to(user) statuses = status.find_new_statuses_allowed_to(user.roles_for_project(project), tracker) statuses << status unless statuses.empty? - statuses.uniq.sort + statuses = statuses.uniq.sort + blocked? ? statuses.reject {|s| s.is_closed?} : statuses end # Returns the mail adresses of users that should be notified for the issue diff --git a/test/fixtures/issue_relations.yml b/test/fixtures/issue_relations.yml new file mode 100644 index 000000000..fb4de48c2 --- /dev/null +++ b/test/fixtures/issue_relations.yml @@ -0,0 +1,7 @@ +issue_relation_001: + id: 1 + issue_from_id: 10 + issue_to_id: 9 + relation_type: blocks + delay: + diff --git a/test/fixtures/issues.yml b/test/fixtures/issues.yml index b66f2eb41..8c8cfbdd6 100644 --- a/test/fixtures/issues.yml +++ b/test/fixtures/issues.yml @@ -125,4 +125,35 @@ issues_008: start_date: due_date: lock_version: 0 - +issues_009: + created_on: <%= 1.minute.ago.to_date.to_s(:db) %> + project_id: 5 + updated_on: <%= 1.minute.ago.to_date.to_s(:db) %> + priority_id: 5 + subject: Blocked Issue + id: 9 + fixed_version_id: + category_id: + description: This is an issue that is blocked by issue #10 + tracker_id: 1 + assigned_to_id: + author_id: 2 + status_id: 1 + start_date: <%= Date.today.to_s(:db) %> + due_date: <%= 1.days.from_now.to_date.to_s(:db) %> +issues_010: + created_on: <%= 1.minute.ago.to_date.to_s(:db) %> + project_id: 5 + updated_on: <%= 1.minute.ago.to_date.to_s(:db) %> + priority_id: 5 + subject: Issue Doing the Blocking + id: 10 + fixed_version_id: + category_id: + description: This is an issue that blocks issue #9 + tracker_id: 1 + assigned_to_id: + author_id: 2 + status_id: 1 + start_date: <%= Date.today.to_s(:db) %> + due_date: <%= 1.days.from_now.to_date.to_s(:db) %> diff --git a/test/unit/issue_test.rb b/test/unit/issue_test.rb index b2eee22b9..a6710edc0 100644 --- a/test/unit/issue_test.rb +++ b/test/unit/issue_test.rb @@ -20,7 +20,7 @@ require File.dirname(__FILE__) + '/../test_helper' class IssueTest < Test::Unit::TestCase fixtures :projects, :users, :members, :member_roles, :trackers, :projects_trackers, - :issue_statuses, :issue_categories, + :issue_statuses, :issue_categories, :issue_relations, :workflows, :enumerations, :issues, :custom_fields, :custom_fields_projects, :custom_fields_trackers, :custom_values, @@ -234,6 +234,32 @@ class IssueTest < Test::Unit::TestCase assert_nil TimeEntry.find_by_issue_id(1) end + def test_blocked + blocked_issue = Issue.find(9) + blocking_issue = Issue.find(10) + + assert blocked_issue.blocked? + assert !blocking_issue.blocked? + end + + def test_blocked_issues_dont_allow_closed_statuses + blocked_issue = Issue.find(9) + + allowed_statuses = blocked_issue.new_statuses_allowed_to(users(:users_002)) + assert !allowed_statuses.empty? + closed_statuses = allowed_statuses.select {|st| st.is_closed?} + assert closed_statuses.empty? + end + + def test_unblocked_issues_allow_closed_statuses + blocking_issue = Issue.find(10) + + allowed_statuses = blocking_issue.new_statuses_allowed_to(users(:users_002)) + assert !allowed_statuses.empty? + closed_statuses = allowed_statuses.select {|st| st.is_closed?} + assert !closed_statuses.empty? + end + def test_overdue assert Issue.new(:due_date => 1.day.ago.to_date).overdue? assert !Issue.new(:due_date => Date.today).overdue?