@@ -0,0 +1,18 | |||
|
1 | class ProjectEnumerationsController < ApplicationController | |
|
2 | before_filter :find_project | |
|
3 | before_filter :authorize | |
|
4 | ||
|
5 | def save | |
|
6 | if request.post? && params[:enumerations] | |
|
7 | Project.transaction do | |
|
8 | params[:enumerations].each do |id, activity| | |
|
9 | @project.update_or_create_time_entry_activity(id, activity) | |
|
10 | end | |
|
11 | end | |
|
12 | flash[:notice] = l(:notice_successful_update) | |
|
13 | end | |
|
14 | ||
|
15 | redirect_to :controller => 'projects', :action => 'settings', :tab => 'activities', :id => @project | |
|
16 | end | |
|
17 | ||
|
18 | end |
@@ -0,0 +1,142 | |||
|
1 | require File.dirname(__FILE__) + '/../test_helper' | |
|
2 | ||
|
3 | class ProjectEnumerationsControllerTest < ActionController::TestCase | |
|
4 | fixtures :all | |
|
5 | ||
|
6 | def setup | |
|
7 | @request.session[:user_id] = nil | |
|
8 | Setting.default_language = 'en' | |
|
9 | end | |
|
10 | ||
|
11 | def test_save_to_override_system_activities | |
|
12 | @request.session[:user_id] = 2 # manager | |
|
13 | billable_field = TimeEntryActivityCustomField.find_by_name("Billable") | |
|
14 | ||
|
15 | post :save, :id => 1, :enumerations => { | |
|
16 | "9"=> {"parent_id"=>"9", "custom_field_values"=>{"7" => "1"}, "active"=>"0"}, # Design, De-activate | |
|
17 | "10"=> {"parent_id"=>"10", "custom_field_values"=>{"7"=>"0"}, "active"=>"1"}, # Development, Change custom value | |
|
18 | "14"=>{"parent_id"=>"14", "custom_field_values"=>{"7"=>"1"}, "active"=>"1"}, # Inactive Activity, Activate with custom value | |
|
19 | "11"=>{"parent_id"=>"11", "custom_field_values"=>{"7"=>"1"}, "active"=>"1"} # QA, no changes | |
|
20 | } | |
|
21 | ||
|
22 | assert_response :redirect | |
|
23 | assert_redirected_to 'projects/ecookbook/settings/activities' | |
|
24 | ||
|
25 | # Created project specific activities... | |
|
26 | project = Project.find('ecookbook') | |
|
27 | ||
|
28 | # ... Design | |
|
29 | design = project.time_entry_activities.find_by_name("Design") | |
|
30 | assert design, "Project activity not found" | |
|
31 | ||
|
32 | assert_equal 9, design.parent_id # Relate to the system activity | |
|
33 | assert_not_equal design.parent.id, design.id # Different records | |
|
34 | assert_equal design.parent.name, design.name # Same name | |
|
35 | assert !design.active? | |
|
36 | ||
|
37 | # ... Development | |
|
38 | development = project.time_entry_activities.find_by_name("Development") | |
|
39 | assert development, "Project activity not found" | |
|
40 | ||
|
41 | assert_equal 10, development.parent_id # Relate to the system activity | |
|
42 | assert_not_equal development.parent.id, development.id # Different records | |
|
43 | assert_equal development.parent.name, development.name # Same name | |
|
44 | assert development.active? | |
|
45 | assert_equal "0", development.custom_value_for(billable_field).value | |
|
46 | ||
|
47 | # ... Inactive Activity | |
|
48 | previously_inactive = project.time_entry_activities.find_by_name("Inactive Activity") | |
|
49 | assert previously_inactive, "Project activity not found" | |
|
50 | ||
|
51 | assert_equal 14, previously_inactive.parent_id # Relate to the system activity | |
|
52 | assert_not_equal previously_inactive.parent.id, previously_inactive.id # Different records | |
|
53 | assert_equal previously_inactive.parent.name, previously_inactive.name # Same name | |
|
54 | assert previously_inactive.active? | |
|
55 | assert_equal "1", previously_inactive.custom_value_for(billable_field).value | |
|
56 | ||
|
57 | # ... QA | |
|
58 | assert_equal nil, project.time_entry_activities.find_by_name("QA"), "Custom QA activity created when it wasn't modified" | |
|
59 | end | |
|
60 | ||
|
61 | def test_save_will_update_project_specific_activities | |
|
62 | @request.session[:user_id] = 2 # manager | |
|
63 | ||
|
64 | project_activity = TimeEntryActivity.new({ | |
|
65 | :name => 'Project Specific', | |
|
66 | :parent => TimeEntryActivity.find(:first), | |
|
67 | :project => Project.find(1), | |
|
68 | :active => true | |
|
69 | }) | |
|
70 | assert project_activity.save | |
|
71 | project_activity_two = TimeEntryActivity.new({ | |
|
72 | :name => 'Project Specific Two', | |
|
73 | :parent => TimeEntryActivity.find(:last), | |
|
74 | :project => Project.find(1), | |
|
75 | :active => true | |
|
76 | }) | |
|
77 | assert project_activity_two.save | |
|
78 | ||
|
79 | ||
|
80 | post :save, :id => 1, :enumerations => { | |
|
81 | project_activity.id => {"custom_field_values"=>{"7" => "1"}, "active"=>"0"}, # De-activate | |
|
82 | project_activity_two.id => {"custom_field_values"=>{"7" => "1"}, "active"=>"0"} # De-activate | |
|
83 | } | |
|
84 | ||
|
85 | assert_response :redirect | |
|
86 | assert_redirected_to 'projects/ecookbook/settings/activities' | |
|
87 | ||
|
88 | # Created project specific activities... | |
|
89 | project = Project.find('ecookbook') | |
|
90 | assert_equal 2, project.time_entry_activities.count | |
|
91 | ||
|
92 | activity_one = project.time_entry_activities.find_by_name(project_activity.name) | |
|
93 | assert activity_one, "Project activity not found" | |
|
94 | assert_equal project_activity.id, activity_one.id | |
|
95 | assert !activity_one.active? | |
|
96 | ||
|
97 | activity_two = project.time_entry_activities.find_by_name(project_activity_two.name) | |
|
98 | assert activity_two, "Project activity not found" | |
|
99 | assert_equal project_activity_two.id, activity_two.id | |
|
100 | assert !activity_two.active? | |
|
101 | end | |
|
102 | ||
|
103 | def test_save_when_creating_new_activities_will_convert_existing_data | |
|
104 | assert_equal 3, TimeEntry.find_all_by_activity_id_and_project_id(9, 1).size | |
|
105 | ||
|
106 | @request.session[:user_id] = 2 # manager | |
|
107 | post :save, :id => 1, :enumerations => { | |
|
108 | "9"=> {"parent_id"=>"9", "custom_field_values"=>{"7" => "1"}, "active"=>"0"} # Design, De-activate | |
|
109 | } | |
|
110 | assert_response :redirect | |
|
111 | ||
|
112 | # No more TimeEntries using the system activity | |
|
113 | assert_equal 0, TimeEntry.find_all_by_activity_id_and_project_id(9, 1).size, "Time Entries still assigned to system activities" | |
|
114 | # All TimeEntries using project activity | |
|
115 | project_specific_activity = TimeEntryActivity.find_by_parent_id_and_project_id(9, 1) | |
|
116 | assert_equal 3, TimeEntry.find_all_by_activity_id_and_project_id(project_specific_activity.id, 1).size, "No Time Entries assigned to the project activity" | |
|
117 | end | |
|
118 | ||
|
119 | def test_save_when_creating_new_activities_will_not_convert_existing_data_if_an_exception_is_raised | |
|
120 | # TODO: Need to cause an exception on create but these tests | |
|
121 | # aren't setup for mocking. Just create a record now so the | |
|
122 | # second one is a dupicate | |
|
123 | parent = TimeEntryActivity.find(9) | |
|
124 | TimeEntryActivity.create!({:name => parent.name, :project_id => 1, :position => parent.position, :active => true}) | |
|
125 | TimeEntry.create!({:project_id => 1, :hours => 1.0, :user => User.find(1), :issue_id => 3, :activity_id => 10, :spent_on => '2009-01-01'}) | |
|
126 | ||
|
127 | assert_equal 3, TimeEntry.find_all_by_activity_id_and_project_id(9, 1).size | |
|
128 | assert_equal 1, TimeEntry.find_all_by_activity_id_and_project_id(10, 1).size | |
|
129 | ||
|
130 | @request.session[:user_id] = 2 # manager | |
|
131 | post :save, :id => 1, :enumerations => { | |
|
132 | "9"=> {"parent_id"=>"9", "custom_field_values"=>{"7" => "1"}, "active"=>"0"}, # Design | |
|
133 | "10"=> {"parent_id"=>"10", "custom_field_values"=>{"7"=>"0"}, "active"=>"1"} # Development, Change custom value | |
|
134 | } | |
|
135 | assert_response :redirect | |
|
136 | ||
|
137 | # TimeEntries shouldn't have been reassigned on the failed record | |
|
138 | assert_equal 3, TimeEntry.find_all_by_activity_id_and_project_id(9, 1).size, "Time Entries are not assigned to system activities" | |
|
139 | # TimeEntries shouldn't have been reassigned on the saved record either | |
|
140 | assert_equal 1, TimeEntry.find_all_by_activity_id_and_project_id(10, 1).size, "Time Entries are not assigned to system activities" | |
|
141 | end | |
|
142 | end |
@@ -238,19 +238,6 class ProjectsController < ApplicationController | |||
|
238 | 238 | @project = nil |
|
239 | 239 | end |
|
240 | 240 | |
|
241 | def save_activities | |
|
242 | if request.post? && params[:enumerations] | |
|
243 | Project.transaction do | |
|
244 | params[:enumerations].each do |id, activity| | |
|
245 | @project.update_or_create_time_entry_activity(id, activity) | |
|
246 | end | |
|
247 | end | |
|
248 | flash[:notice] = l(:notice_successful_update) | |
|
249 | end | |
|
250 | ||
|
251 | redirect_to :controller => 'projects', :action => 'settings', :tab => 'activities', :id => @project | |
|
252 | end | |
|
253 | ||
|
254 | 241 | def reset_activities |
|
255 | 242 | @project.time_entry_activities.each do |time_entry_activity| |
|
256 | 243 | time_entry_activity.destroy(time_entry_activity.parent) |
@@ -1,4 +1,4 | |||
|
1 |
<% form_tag({:controller => 'projects', :action => 'save |
|
|
1 | <% form_tag({:controller => 'project_enumerations', :action => 'save', :id => @project}, :class => "tabular") do %> | |
|
2 | 2 | |
|
3 | 3 | <table class="list"> |
|
4 | 4 | <thead><tr> |
@@ -200,7 +200,7 ActionController::Routing::Routes.draw do |map| | |||
|
200 | 200 | project_actions.connect 'projects.:format', :action => 'add', :format => /xml/ |
|
201 | 201 | project_actions.connect 'projects/:id/:action', :action => /edit|destroy|archive|unarchive/ |
|
202 | 202 | project_actions.connect 'projects/:id/files/new', :controller => 'files', :action => 'new' |
|
203 |
project_actions.connect 'projects/:id/activities/save', :action => 'save |
|
|
203 | project_actions.connect 'projects/:id/activities/save', :controller => 'project_enumerations', :action => 'save' | |
|
204 | 204 | end |
|
205 | 205 | |
|
206 | 206 | projects.with_options :conditions => {:method => :put} do |project_actions| |
@@ -87,7 +87,7 Redmine::AccessControl.map do |map| | |||
|
87 | 87 | map.permission :view_time_entries, :timelog => [:details, :report] |
|
88 | 88 | map.permission :edit_time_entries, {:timelog => [:edit, :destroy]}, :require => :member |
|
89 | 89 | map.permission :edit_own_time_entries, {:timelog => [:edit, :destroy]}, :require => :loggedin |
|
90 |
map.permission :manage_project_activities, {:projects => [:s |
|
|
90 | map.permission :manage_project_activities, {:projects => [:reset_activities], :project_enumerations => [:save]}, :require => :member | |
|
91 | 91 | end |
|
92 | 92 | |
|
93 | 93 | map.project_module :news do |map| |
@@ -427,138 +427,6 class ProjectsControllerTest < ActionController::TestCase | |||
|
427 | 427 | assert_equal 3, TimeEntry.find_all_by_activity_id_and_project_id(9, 1).size, "TimeEntries still assigned to project specific activity" |
|
428 | 428 | end |
|
429 | 429 | |
|
430 | def test_save_activities_to_override_system_activities | |
|
431 | @request.session[:user_id] = 2 # manager | |
|
432 | billable_field = TimeEntryActivityCustomField.find_by_name("Billable") | |
|
433 | ||
|
434 | post :save_activities, :id => 1, :enumerations => { | |
|
435 | "9"=> {"parent_id"=>"9", "custom_field_values"=>{"7" => "1"}, "active"=>"0"}, # Design, De-activate | |
|
436 | "10"=> {"parent_id"=>"10", "custom_field_values"=>{"7"=>"0"}, "active"=>"1"}, # Development, Change custom value | |
|
437 | "14"=>{"parent_id"=>"14", "custom_field_values"=>{"7"=>"1"}, "active"=>"1"}, # Inactive Activity, Activate with custom value | |
|
438 | "11"=>{"parent_id"=>"11", "custom_field_values"=>{"7"=>"1"}, "active"=>"1"} # QA, no changes | |
|
439 | } | |
|
440 | ||
|
441 | assert_response :redirect | |
|
442 | assert_redirected_to 'projects/ecookbook/settings/activities' | |
|
443 | ||
|
444 | # Created project specific activities... | |
|
445 | project = Project.find('ecookbook') | |
|
446 | ||
|
447 | # ... Design | |
|
448 | design = project.time_entry_activities.find_by_name("Design") | |
|
449 | assert design, "Project activity not found" | |
|
450 | ||
|
451 | assert_equal 9, design.parent_id # Relate to the system activity | |
|
452 | assert_not_equal design.parent.id, design.id # Different records | |
|
453 | assert_equal design.parent.name, design.name # Same name | |
|
454 | assert !design.active? | |
|
455 | ||
|
456 | # ... Development | |
|
457 | development = project.time_entry_activities.find_by_name("Development") | |
|
458 | assert development, "Project activity not found" | |
|
459 | ||
|
460 | assert_equal 10, development.parent_id # Relate to the system activity | |
|
461 | assert_not_equal development.parent.id, development.id # Different records | |
|
462 | assert_equal development.parent.name, development.name # Same name | |
|
463 | assert development.active? | |
|
464 | assert_equal "0", development.custom_value_for(billable_field).value | |
|
465 | ||
|
466 | # ... Inactive Activity | |
|
467 | previously_inactive = project.time_entry_activities.find_by_name("Inactive Activity") | |
|
468 | assert previously_inactive, "Project activity not found" | |
|
469 | ||
|
470 | assert_equal 14, previously_inactive.parent_id # Relate to the system activity | |
|
471 | assert_not_equal previously_inactive.parent.id, previously_inactive.id # Different records | |
|
472 | assert_equal previously_inactive.parent.name, previously_inactive.name # Same name | |
|
473 | assert previously_inactive.active? | |
|
474 | assert_equal "1", previously_inactive.custom_value_for(billable_field).value | |
|
475 | ||
|
476 | # ... QA | |
|
477 | assert_equal nil, project.time_entry_activities.find_by_name("QA"), "Custom QA activity created when it wasn't modified" | |
|
478 | end | |
|
479 | ||
|
480 | def test_save_activities_will_update_project_specific_activities | |
|
481 | @request.session[:user_id] = 2 # manager | |
|
482 | ||
|
483 | project_activity = TimeEntryActivity.new({ | |
|
484 | :name => 'Project Specific', | |
|
485 | :parent => TimeEntryActivity.find(:first), | |
|
486 | :project => Project.find(1), | |
|
487 | :active => true | |
|
488 | }) | |
|
489 | assert project_activity.save | |
|
490 | project_activity_two = TimeEntryActivity.new({ | |
|
491 | :name => 'Project Specific Two', | |
|
492 | :parent => TimeEntryActivity.find(:last), | |
|
493 | :project => Project.find(1), | |
|
494 | :active => true | |
|
495 | }) | |
|
496 | assert project_activity_two.save | |
|
497 | ||
|
498 | ||
|
499 | post :save_activities, :id => 1, :enumerations => { | |
|
500 | project_activity.id => {"custom_field_values"=>{"7" => "1"}, "active"=>"0"}, # De-activate | |
|
501 | project_activity_two.id => {"custom_field_values"=>{"7" => "1"}, "active"=>"0"} # De-activate | |
|
502 | } | |
|
503 | ||
|
504 | assert_response :redirect | |
|
505 | assert_redirected_to 'projects/ecookbook/settings/activities' | |
|
506 | ||
|
507 | # Created project specific activities... | |
|
508 | project = Project.find('ecookbook') | |
|
509 | assert_equal 2, project.time_entry_activities.count | |
|
510 | ||
|
511 | activity_one = project.time_entry_activities.find_by_name(project_activity.name) | |
|
512 | assert activity_one, "Project activity not found" | |
|
513 | assert_equal project_activity.id, activity_one.id | |
|
514 | assert !activity_one.active? | |
|
515 | ||
|
516 | activity_two = project.time_entry_activities.find_by_name(project_activity_two.name) | |
|
517 | assert activity_two, "Project activity not found" | |
|
518 | assert_equal project_activity_two.id, activity_two.id | |
|
519 | assert !activity_two.active? | |
|
520 | end | |
|
521 | ||
|
522 | def test_save_activities_when_creating_new_activities_will_convert_existing_data | |
|
523 | assert_equal 3, TimeEntry.find_all_by_activity_id_and_project_id(9, 1).size | |
|
524 | ||
|
525 | @request.session[:user_id] = 2 # manager | |
|
526 | post :save_activities, :id => 1, :enumerations => { | |
|
527 | "9"=> {"parent_id"=>"9", "custom_field_values"=>{"7" => "1"}, "active"=>"0"} # Design, De-activate | |
|
528 | } | |
|
529 | assert_response :redirect | |
|
530 | ||
|
531 | # No more TimeEntries using the system activity | |
|
532 | assert_equal 0, TimeEntry.find_all_by_activity_id_and_project_id(9, 1).size, "Time Entries still assigned to system activities" | |
|
533 | # All TimeEntries using project activity | |
|
534 | project_specific_activity = TimeEntryActivity.find_by_parent_id_and_project_id(9, 1) | |
|
535 | assert_equal 3, TimeEntry.find_all_by_activity_id_and_project_id(project_specific_activity.id, 1).size, "No Time Entries assigned to the project activity" | |
|
536 | end | |
|
537 | ||
|
538 | def test_save_activities_when_creating_new_activities_will_not_convert_existing_data_if_an_exception_is_raised | |
|
539 | # TODO: Need to cause an exception on create but these tests | |
|
540 | # aren't setup for mocking. Just create a record now so the | |
|
541 | # second one is a dupicate | |
|
542 | parent = TimeEntryActivity.find(9) | |
|
543 | TimeEntryActivity.create!({:name => parent.name, :project_id => 1, :position => parent.position, :active => true}) | |
|
544 | TimeEntry.create!({:project_id => 1, :hours => 1.0, :user => User.find(1), :issue_id => 3, :activity_id => 10, :spent_on => '2009-01-01'}) | |
|
545 | ||
|
546 | assert_equal 3, TimeEntry.find_all_by_activity_id_and_project_id(9, 1).size | |
|
547 | assert_equal 1, TimeEntry.find_all_by_activity_id_and_project_id(10, 1).size | |
|
548 | ||
|
549 | @request.session[:user_id] = 2 # manager | |
|
550 | post :save_activities, :id => 1, :enumerations => { | |
|
551 | "9"=> {"parent_id"=>"9", "custom_field_values"=>{"7" => "1"}, "active"=>"0"}, # Design | |
|
552 | "10"=> {"parent_id"=>"10", "custom_field_values"=>{"7"=>"0"}, "active"=>"1"} # Development, Change custom value | |
|
553 | } | |
|
554 | assert_response :redirect | |
|
555 | ||
|
556 | # TimeEntries shouldn't have been reassigned on the failed record | |
|
557 | assert_equal 3, TimeEntry.find_all_by_activity_id_and_project_id(9, 1).size, "Time Entries are not assigned to system activities" | |
|
558 | # TimeEntries shouldn't have been reassigned on the saved record either | |
|
559 | assert_equal 1, TimeEntry.find_all_by_activity_id_and_project_id(10, 1).size, "Time Entries are not assigned to system activities" | |
|
560 | end | |
|
561 | ||
|
562 | 430 | # A hook that is manually registered later |
|
563 | 431 | class ProjectBasedTemplate < Redmine::Hook::ViewListener |
|
564 | 432 | def view_layouts_base_html_head(context) |
@@ -185,7 +185,7 class RoutingTest < ActionController::IntegrationTest | |||
|
185 | 185 | should_route :post, "/projects/33/files/new", :controller => 'files', :action => 'new', :id => '33' |
|
186 | 186 | should_route :post, "/projects/64/archive", :controller => 'projects', :action => 'archive', :id => '64' |
|
187 | 187 | should_route :post, "/projects/64/unarchive", :controller => 'projects', :action => 'unarchive', :id => '64' |
|
188 |
should_route :post, "/projects/64/activities/save", :controller => 'projects', :action => 'save |
|
|
188 | should_route :post, "/projects/64/activities/save", :controller => 'project_enumerations', :action => 'save', :id => '64' | |
|
189 | 189 | |
|
190 | 190 | should_route :put, "/projects/1.xml", :controller => 'projects', :action => 'edit', :id => '1', :format => 'xml' |
|
191 | 191 |
General Comments 0
You need to be logged in to leave comments.
Login now