Project

General

Profile

« Previous | Next » 

Revision 4053

Refactor: move method, ProjectsController#save_activities to ProjectEnumerationsController#save

View differences:

trunk/app/controllers/project_enumerations_controller.rb
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
trunk/app/controllers/projects_controller.rb
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)
trunk/app/views/projects/settings/_activities.rhtml
1
<% form_tag({:controller => 'projects', :action => 'save_activities', :id => @project}, :class => "tabular") do %>
1
<% form_tag({:controller => 'project_enumerations', :action => 'save', :id => @project}, :class => "tabular") do %>
2 2

  
3 3
<table class="list">
4 4
  <thead><tr>
trunk/config/routes.rb
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_activities'
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|
trunk/lib/redmine.rb
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 => [:save_activities, :reset_activities]}, :require => :member
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|
trunk/test/functional/project_enumerations_controller_test.rb
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
trunk/test/functional/projects_controller_test.rb
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)
trunk/test/integration/routing_test.rb
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_activities', :id => '64'
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

  

Also available in: Unified diff