Commit 9e766d4036b94c0f92b84fa80b22bb02dacbf7a9
1 parent
24bb5d14
Exists in
master
and in
28 other branches
ActionItem628: Squashed commit of the following:
enhancement pending task mail message
list pending tasks in communities/groups where the user is a member and can solve the tasks
loop through users with pending tasks and notify them
determine wheter a user has pending tasks
Showing
7 changed files
with
158 additions
and
0 deletions
Show diff stats
| ... | ... | @@ -0,0 +1,16 @@ |
| 1 | +class PendingTaskNotifier < ActionMailer::Base | |
| 2 | + | |
| 3 | + def notification(person) | |
| 4 | + recipients person.email | |
| 5 | + from "#{person.environment.name} <#{person.environment.contact_email}>" | |
| 6 | + subject _("%s - Pending tasks") % person.environment.name | |
| 7 | + body :person => person, | |
| 8 | + :tasks => person.tasks.pending, | |
| 9 | + :organizations_with_pending_tasks => person.organizations_with_pending_tasks, | |
| 10 | + :environment => person.environment.name, | |
| 11 | + :url => url_for(:host => person.environment.default_hostname, :controller => 'home'), | |
| 12 | + :default_hostname => person.environment.default_hostname, | |
| 13 | + :url_for_pending_tasks => url_for(:host => person.environment.default_hostname, :controller => 'tasks', :profile => person.identifier) | |
| 14 | + end | |
| 15 | + | |
| 16 | +end | ... | ... |
app/models/person.rb
| ... | ... | @@ -119,4 +119,22 @@ class Person < Profile |
| 119 | 119 | environment.person_template |
| 120 | 120 | end |
| 121 | 121 | |
| 122 | + def self.with_pending_tasks | |
| 123 | + Person.find(:all).select{ |person| !person.tasks.pending.empty? or person.has_organization_pending_tasks? } | |
| 124 | + end | |
| 125 | + | |
| 126 | + def has_organization_pending_tasks? | |
| 127 | + self.memberships.any?{ |group| group.tasks.pending.any?{ |task| self.has_permission?(task.permission, group) } } | |
| 128 | + end | |
| 129 | + | |
| 130 | + def organizations_with_pending_tasks | |
| 131 | + self.memberships.select do |organization| | |
| 132 | + organization.tasks.pending.any?{|task| self.has_permission?(task.permission, organization)} | |
| 133 | + end | |
| 134 | + end | |
| 135 | + | |
| 136 | + def pending_tasks_for_organization(organization) | |
| 137 | + organization.tasks.pending.select{|task| self.has_permission?(task.permission, organization)} | |
| 138 | + end | |
| 139 | + | |
| 122 | 140 | end | ... | ... |
| ... | ... | @@ -0,0 +1,22 @@ |
| 1 | +<%= _("Dear %s") % @person.name %>, | |
| 2 | + | |
| 3 | +<%= _("You have %d pending task(s).") % @tasks.size %> | |
| 4 | + | |
| 5 | +<%= @tasks.map{|i| " * #{i.description}"}.join("\n") %> | |
| 6 | + | |
| 7 | +<%= _("Click in address below to process task(s):") %> | |
| 8 | + | |
| 9 | +<%= @url_for_pending_tasks %> | |
| 10 | +<% @organizations_with_pending_tasks.each do |organization| %> | |
| 11 | +<% pending_tasks = @person.pending_tasks_for_organization(organization) %> | |
| 12 | +<%= _("%s has %d pending task(s).") % [organization.name, pending_tasks.size] %> | |
| 13 | + | |
| 14 | +<%= pending_tasks.map{|i| " * #{i.description}"}.join("\n") %> | |
| 15 | + | |
| 16 | +<%= _("Click in address below to process task(s):") %> | |
| 17 | + | |
| 18 | +<%= url_for(:host => @default_hostname, :controller => 'tasks', :profile => organization.identifier) %> | |
| 19 | +<% end %> | |
| 20 | +-- | |
| 21 | +<%= _('%s environment system') % @environment %> | |
| 22 | +<%= @url %> | ... | ... |
test/fixtures/roles.yml
| ... | ... | @@ -28,6 +28,7 @@ four: |
| 28 | 28 | - manage_environment_roles |
| 29 | 29 | - manage_environment_validators |
| 30 | 30 | - moderate_comments |
| 31 | + - perform_task | |
| 31 | 32 | profile_admin: |
| 32 | 33 | id: 5 |
| 33 | 34 | key: 'profile_admin' |
| ... | ... | @@ -37,6 +38,7 @@ profile_admin: |
| 37 | 38 | - edit_profile_design |
| 38 | 39 | - moderate_comments |
| 39 | 40 | - destroy_profile |
| 41 | + - perform_task | |
| 40 | 42 | profile_member: |
| 41 | 43 | id: 6 |
| 42 | 44 | key: 'profile_member' | ... | ... |
| ... | ... | @@ -0,0 +1,43 @@ |
| 1 | +require File.dirname(__FILE__) + '/../test_helper' | |
| 2 | + | |
| 3 | +class PendingTaskNotifierTest < Test::Unit::TestCase | |
| 4 | + FIXTURES_PATH = File.dirname(__FILE__) + '/../fixtures' | |
| 5 | + CHARSET = "utf-8" | |
| 6 | + | |
| 7 | + def setup | |
| 8 | + ActionMailer::Base.delivery_method = :test | |
| 9 | + ActionMailer::Base.perform_deliveries = true | |
| 10 | + ActionMailer::Base.deliveries = [] | |
| 11 | + | |
| 12 | + @expected = TMail::Mail.new | |
| 13 | + @expected.set_content_type "text", "plain", { "charset" => CHARSET } | |
| 14 | + end | |
| 15 | + | |
| 16 | + should 'be able to deliver notification' do | |
| 17 | + p = create_user('maelcum').person | |
| 18 | + response = PendingTaskNotifier.deliver_notification(p) | |
| 19 | + assert_equal 'Pending tasks', response.subject | |
| 20 | + assert_equal p.email, response.to[0] | |
| 21 | + end | |
| 22 | + | |
| 23 | + should 'list organization pending tasks' do | |
| 24 | + p = create_user('maelcum').person | |
| 25 | + c = Community.create!(:name => 'my test community') | |
| 26 | + c.add_admin(p) | |
| 27 | + c.tasks << Task.new | |
| 28 | + | |
| 29 | + response = PendingTaskNotifier.deliver_notification(p) | |
| 30 | + assert_match /Generic task/, response.body | |
| 31 | + end | |
| 32 | + | |
| 33 | + private | |
| 34 | + | |
| 35 | + def read_fixture(action) | |
| 36 | + IO.readlines("#{FIXTURES_PATH}/mail_sender/#{action}") | |
| 37 | + end | |
| 38 | + | |
| 39 | + def encode(subject) | |
| 40 | + quoted_printable(subject, CHARSET) | |
| 41 | + end | |
| 42 | + | |
| 43 | +end | ... | ... |
test/unit/person_test.rb
| ... | ... | @@ -326,4 +326,54 @@ class PersonTest < Test::Unit::TestCase |
| 326 | 326 | end |
| 327 | 327 | end |
| 328 | 328 | |
| 329 | + should 'person has pending tasks' do | |
| 330 | + p1 = create_user('user_with_tasks').person | |
| 331 | + p1.tasks << Task.new | |
| 332 | + p2 = create_user('user_without_tasks').person | |
| 333 | + assert_includes Person.with_pending_tasks, p1 | |
| 334 | + assert_not_includes Person.with_pending_tasks, p2 | |
| 335 | + end | |
| 336 | + | |
| 337 | + should 'person has group with pending tasks' do | |
| 338 | + p1 = create_user('user_with_tasks').person | |
| 339 | + c1 = Community.create!(:name => 'my test community') | |
| 340 | + c1.tasks << Task.new | |
| 341 | + assert !c1.tasks.pending.empty? | |
| 342 | + c1.add_admin(p1) | |
| 343 | + | |
| 344 | + c2 = Community.create!(:name => 'my other test community') | |
| 345 | + p2 = create_user('user_without_tasks').person | |
| 346 | + c2.add_admin(p2) | |
| 347 | + | |
| 348 | + assert_includes Person.with_pending_tasks, p1 | |
| 349 | + assert_not_includes Person.with_pending_tasks, p2 | |
| 350 | + end | |
| 351 | + | |
| 352 | + should 'not allow simple member to view group pending tasks' do | |
| 353 | + c = Community.create!(:name => 'my test community') | |
| 354 | + c.tasks << Task.new | |
| 355 | + p = create_user('user_without_tasks').person | |
| 356 | + c.add_member(p) | |
| 357 | + | |
| 358 | + assert_not_includes Person.with_pending_tasks, p | |
| 359 | + end | |
| 360 | + | |
| 361 | + should 'person has organization pending tasks' do | |
| 362 | + c = Community.create!(:name => 'my test community') | |
| 363 | + c.tasks << Task.new | |
| 364 | + p = create_user('user_with_tasks').person | |
| 365 | + c.add_admin(p) | |
| 366 | + | |
| 367 | + assert p.has_organization_pending_tasks? | |
| 368 | + end | |
| 369 | + | |
| 370 | + should 'select organization pending tasks' do | |
| 371 | + c = Community.create!(:name => 'my test community') | |
| 372 | + c.tasks << Task.new | |
| 373 | + p = create_user('user_with_tasks').person | |
| 374 | + c.add_admin(p) | |
| 375 | + | |
| 376 | + assert_equal p.pending_tasks_for_organization(c), c.tasks | |
| 377 | + end | |
| 378 | + | |
| 329 | 379 | end | ... | ... |