When the user creates a new task against a backlog item, then can set a
checkbox that marks the item as completed. If the task is saved, then
the item will be marked as completed. This is only available for an
assigned item on an active sprint and only to the item owner.
Signed-off-by: Darryl L. Pierce <mcpierce(a)gmail.com>
---
app/controllers/tasks_controller.rb | 5 +-
app/models/backlog_item.rb | 12 ++++-
app/views/tasks/_edit.html.erb | 71 +++++++++++++++++-------------
doc/ChangeLog | 1 +
test/functional/tasks_controller_test.rb | 11 +++++
test/functional/user_items_test.rb | 4 +-
6 files changed, 67 insertions(+), 37 deletions(-)
diff --git a/app/controllers/tasks_controller.rb b/app/controllers/tasks_controller.rb
index f3e6709..600fa97 100644
--- a/app/controllers/tasks_controller.rb
+++ b/app/controllers/tasks_controller.rb
@@ -63,13 +63,14 @@ class TasksController < ApplicationController
Task.transaction do
@task = Task.new(params[:task])
@task.primary = @user
- @task.backlog_item = @backlog_item
+ @task.backlog_item_id = @backlog_item.id
+ @task.backlog_item.completed if params[:completed]
if @task.backup_id && !@sprint.is_team_member?((a)task.backup)
report_error "Backup must be a member of the sprint team."
else
respond_to do |format|
- if @task.save
+ if @task.save && @task.backlog_item.save
flash[:message] = "Recorded #{(a)task.hours} hours against this backlog
item."
format.html { redirect_to task_path(@task) }
else
diff --git a/app/models/backlog_item.rb b/app/models/backlog_item.rb
index 07dc2b4..a3c0598 100644
--- a/app/models/backlog_item.rb
+++ b/app/models/backlog_item.rb
@@ -33,7 +33,7 @@ class BacklogItem < ActiveRecord::Base
belongs_to :owner, :class_name => 'User', :foreign_key =>
'owner_id'
belongs_to :backup, :class_name => 'User', :foreign_key =>
'backup_id'
- has_many :tasks
+ has_many :tasks, :dependent => :destroy
has_many :remaining_hours_estimates
has_and_belongs_to_many :messages, :join_table => :backlog_items_messages
@@ -172,8 +172,14 @@ class BacklogItem < ActiveRecord::Base
end
# Returns whether the user can complete this backlog item.
- def can_complete?(user)
- owner?(user) && (state != STATE_COMPLETED) && !tasks.empty?
+ # The +with_tasks+ argument is used to check this rule regardless of
+ # whether there are tasks.
+ def can_complete?(user, with_tasks=false)
+ if with_tasks
+ owner?(user) && (state != STATE_COMPLETED)
+ else
+ owner?(user) && (state != STATE_COMPLETED) && !tasks.empty?
+ end
end
# Returns whether the user can mark the item as blocked.
diff --git a/app/views/tasks/_edit.html.erb b/app/views/tasks/_edit.html.erb
index e3d58d5..c79c92c 100644
--- a/app/views/tasks/_edit.html.erb
+++ b/app/views/tasks/_edit.html.erb
@@ -6,49 +6,60 @@
<caption><%= "#{(a)task.new_record? ? 'Create' : 'Edit'}
A Task" %></caption>
<tbody>
<tr>
- <td class="label-required">When:</td>
- <td class="value">
- <%= form.date_select :when_entered %>
- <%= error_message_on(:task, :when_entered) %>
- </td>
+ <td class="label-required">When:</td>
+ <td class="value">
+ <%= form.date_select :when_entered %>
+ <%= error_message_on(:task, :when_entered) %>
+ </td>
</tr>
<tr>
- <td class="label-required">Primary:</td>
- <td class="value"><%= @task.primary.display_name
%></td>
+ <td class="label-required">Primary:</td>
+ <td class="value"><%= @task.primary.display_name %></td>
</tr>
<tr>
- <td class="label">Backup:</td>
- <td class="value">
- <%= collection_select :task, :backup_id, @users, :id,
- :display_name, {:include_blank => true} %>
- <%= error_message_on(:task, :backup_id) %>
- </td>
+ <td class="label">Backup:</td>
+ <td class="value">
+ <%= collection_select :task, :backup_id, @users, :id,
+ :display_name, {:include_blank => true} %>
+ <%= error_message_on(:task, :backup_id) %>
+ </td>
</tr>
<tr>
- <td class="label-required">Hours:</td>
- <td class="value">
- <%= form.text_field :hours, :size => 3, :maxlength => 5 %>
- <%= error_message_on(:task, :hours) %>
- </td>
+ <td class="label-required">Hours:</td>
+ <td class="value">
+ <%= form.text_field :hours, :size => 3, :maxlength => 5 %>
+ <%= error_message_on(:task, :hours) %>
+ </td>
</tr>
<tr>
- <td class="label">
+ <td class="label">
Description:
(you can use wiki markup)
</td>
- <td class="value">
- <%= form.text_area :description, :cols => 100, :rows => 10 %>
- <%= error_message_on(:task, :description) %>
- </td>
+ <td class="value">
+ <%= form.text_area :description, :cols => 100, :rows => 10 %>
+ <%= error_message_on(:task, :description) %>
+ </td>
</tr>
+
+ <% if @backlog_item.can_complete?(@user, true) %>
<tr>
- <td class="buttons" colspan="2">
- <% if @task.new_record? %>
- <%= submit_tag "Create", :class => 'button' %>
- <% else %>
- <%= submit_tag "Update", :class => 'button' %>
- <% end %>
- </td>
+ <td class="label" />
+ <td class="value">
+ <%= check_box_tag :completed, true, params[:completed] %>
+ <%= label_tag :completed, "Mark this item as completed." %>
+ </td>
+ </tr>
+ <% end %>
+
+ <tr>
+ <td class="buttons" colspan="2">
+ <% if @task.new_record? %>
+ <%= submit_tag "Create", :class => 'button' %>
+ <% else %>
+ <%= submit_tag "Update", :class => 'button' %>
+ <% end %>
+ </td>
</tr>
</tbody>
</table>
diff --git a/doc/ChangeLog b/doc/ChangeLog
index 6ad0279..8169802 100644
--- a/doc/ChangeLog
+++ b/doc/ChangeLog
@@ -1,5 +1,6 @@
Change Log (0.3.0):
* #156 - Backlog items can be marked as blocked.
+ * #157 - Items can be marked completed when a task is added.
* #167 - Blocker messages are included in the daily updates email.
* #175 - Fixed display of products for an unapproved project. (BUG)
* #176 - Added a breadcrumb trail to the navigation bar.
diff --git a/test/functional/tasks_controller_test.rb
b/test/functional/tasks_controller_test.rb
index 5ecf7ee..24eaa29 100644
--- a/test/functional/tasks_controller_test.rb
+++ b/test/functional/tasks_controller_test.rb
@@ -226,6 +226,17 @@ class TasksControllerTest < ActionController::TestCase
result = Task.find_by_description(@new_task[:description])
assert result, "Task should have been created."
assert_redirected_to task_path(result)
+ assert !result.backlog_item.completed?, "Backlog item should not have been
marked completed."
+ end
+
+ # Ensures that creating a task that marks the item completed works as expected.
+ def test_create_and_complete
+ post :create, {:item => @item.id, :task => @new_task, :completed => true},
{:user_id => @owner.id}
+
+ result = Task.find_by_description(@new_task[:description])
+ assert result, "Task should have been created."
+ assert_redirected_to task_path(result)
+ assert result.backlog_item.completed?, "Item should have been marked as
completed."
end
# Ensures anonymous users can't update a task.
diff --git a/test/functional/user_items_test.rb b/test/functional/user_items_test.rb
index ae17fb1..d49bd44 100644
--- a/test/functional/user_items_test.rb
+++ b/test/functional/user_items_test.rb
@@ -193,12 +193,12 @@ class UserItemsTest < ActionController::TestCase
# Ensures that completing works as expected.
def test_complete
- get :complete,{:id => @owned_item.id}, {:user_id => @member.id}
+ get :complete,{:id => @owned_item.id}, {:user_id => @owned_item.owner_id}
assert_redirected_to items_path(:sprint => @sprint)
result = BacklogItem.find_by_id((a)owned_item.id)
assert_equal BacklogItem::STATE_COMPLETED, result.state,
- "Items hould be marked as completed."
+ "Item should be marked as completed."
end
# Ensures an anonymous user can't reopen an item.
--
1.6.0.6