Feature #29286 » 0001-Option-to-set-default-time-entry-activity-per-role.patch
app/helpers/timelog_helper.rb | ||
---|---|---|
26 | 26 |
def activity_collection_for_select_options(time_entry=nil, project=nil) |
27 | 27 |
project ||= time_entry.try(:project) |
28 | 28 |
project ||= @project |
29 |
if project.nil? |
|
30 |
activities = TimeEntryActivity.shared.active |
|
31 |
else |
|
32 |
activities = project.activities |
|
33 |
end |
|
29 | ||
30 |
activities = TimeEntryActivity.allowed_activities(project) |
|
34 | 31 | |
35 | 32 |
collection = [] |
36 | 33 |
if time_entry && time_entry.activity && !time_entry.activity.active? |
... | ... | |
42 | 39 |
collection |
43 | 40 |
end |
44 | 41 | |
42 |
def default_activity(time_entry) |
|
43 |
if @project |
|
44 |
time_entry.activity_id |
|
45 |
else |
|
46 |
TimeEntryActivity.default_activity_id(User.current, time_entry.project) |
|
47 |
end |
|
48 |
end |
|
49 | ||
45 | 50 |
def select_hours(data, criteria, value) |
46 | 51 |
if value.to_s.empty? |
47 | 52 |
data.select {|row| row[criteria].blank? } |
app/models/role.rb | ||
---|---|---|
58 | 58 |
where("#{compare} builtin = 0") |
59 | 59 |
} |
60 | 60 | |
61 |
belongs_to :default_time_entry_activity, :class_name => "TimeEntryActivity" |
|
62 | ||
61 | 63 |
before_destroy :check_deletable |
62 | 64 |
has_many :workflow_rules, :dependent => :delete_all |
63 | 65 |
has_and_belongs_to_many :custom_fields, :join_table => "#{table_name_prefix}custom_fields_roles#{table_name_suffix}", :foreign_key => "role_id" |
... | ... | |
96 | 98 |
'managed_role_ids', |
97 | 99 |
'permissions', |
98 | 100 |
'permissions_all_trackers', |
99 |
'permissions_tracker_ids' |
|
101 |
'permissions_tracker_ids', |
|
102 |
'default_time_entry_activity_id' |
|
100 | 103 | |
101 | 104 |
# Copies attributes from another role, arg can be an id or a Role |
102 | 105 |
def copy_from(arg, options={}) |
app/models/time_entry.rb | ||
---|---|---|
91 | 91 |
def initialize(attributes=nil, *args) |
92 | 92 |
super |
93 | 93 |
if new_record? && self.activity.nil? |
94 |
if default_activity = TimeEntryActivity.default |
|
95 |
self.activity_id = default_activity.id |
|
96 |
end |
|
94 |
self.activity_id = TimeEntryActivity.default_activity_id(self.user, self.project) |
|
97 | 95 |
self.hours = nil if hours == 0 |
98 | 96 |
end |
99 | 97 |
end |
app/models/time_entry_activity.rb | ||
---|---|---|
35 | 35 |
def transfer_relations(to) |
36 | 36 |
objects.update_all(:activity_id => to.id) |
37 | 37 |
end |
38 | ||
39 |
def self.default_activity_id(user=nil, project=nil) |
|
40 |
default_activities = [] |
|
41 |
default_activity = nil |
|
42 |
allowed_activities = self.allowed_activities(project) |
|
43 | ||
44 |
if project && user |
|
45 |
user_membership = user.membership(project) |
|
46 |
if user_membership |
|
47 |
default_activities = user_membership.roles.where.not(:default_time_entry_activity_id => nil).sort.pluck(:default_time_entry_activity_id) |
|
48 |
end |
|
49 |
end |
|
50 | ||
51 |
global_activity = self.default |
|
52 |
if global_activity |
|
53 |
default_activities << global_activity.id unless default_activities.include?(global_activity.id) |
|
54 |
end |
|
55 | ||
56 |
default_activities.each do |id| |
|
57 |
default_activity = allowed_activities.detect{ |a| a.id == id || a.parent_id == id } |
|
58 |
break unless default_activity.nil? |
|
59 |
end |
|
60 | ||
61 |
default_activity.id unless default_activity.nil? |
|
62 |
end |
|
63 | ||
64 |
# Returns the available activities for the time entry |
|
65 |
def self.allowed_activities(project=nil) |
|
66 |
if project.nil? |
|
67 |
activities = TimeEntryActivity.shared.active |
|
68 |
else |
|
69 |
activities = project.activities |
|
70 |
end |
|
71 |
end |
|
38 | 72 |
end |
app/views/roles/_form.html.erb | ||
---|---|---|
38 | 38 |
<%= hidden_field_tag 'role[managed_role_ids][]', '' %> |
39 | 39 |
<% end %> |
40 | 40 | |
41 |
<% unless @role.anonymous? %> |
|
42 |
<p><%= f.select :default_time_entry_activity_id, options_from_collection_for_select(TimeEntryActivity.active.shared, :id, :name, @role.default_time_entry_activity_id), :include_blank => l(:label_none) %></p> |
|
43 |
<% end %> |
|
44 | ||
41 | 45 |
<% if @role.new_record? && @roles.any? %> |
42 | 46 |
<p><label for="copy_workflow_from"><%= l(:label_copy_workflow_from) %></label> |
43 | 47 |
<%= select_tag(:copy_workflow_from, content_tag("option") + options_from_collection_for_select(@roles, :id, :name, params[:copy_workflow_from] || @copy_from.try(:id))) %></p> |
app/views/timelog/new.js.erb | ||
---|---|---|
1 |
$('#time_entry_activity_id').html('<%= escape_javascript options_for_select(activity_collection_for_select_options(@time_entry), @time_entry.activity_id) %>');
|
|
1 |
$('#time_entry_activity_id').html('<%= escape_javascript options_for_select(activity_collection_for_select_options(@time_entry), default_activity(@time_entry)) %>');
|
|
2 | 2 |
$('#time_entry_issue').html('<%= escape_javascript link_to_issue(@time_entry.issue) if @time_entry.issue.try(:visible?) %>'); |
db/migrate/20180806215628_add_default_time_entry_activity_to_roles.rb | ||
---|---|---|
1 |
class AddDefaultTimeEntryActivityToRoles < ActiveRecord::Migration[5.2] |
|
2 |
def change |
|
3 |
add_column :roles, :default_time_entry_activity_id, :int |
|
4 |
end |
|
5 |
end |
test/functional/timelog_controller_test.rb | ||
---|---|---|
86 | 86 |
assert_response 403 |
87 | 87 |
end |
88 | 88 | |
89 |
def test_new_should_select_default_activity |
|
89 |
def test_new_should_select_default_role_activity |
|
90 |
developer = Role.find(2) |
|
91 |
developer.default_time_entry_activity_id = 9 |
|
92 |
developer.save! |
|
93 | ||
94 |
@request.session[:user_id] = 3 |
|
95 |
get :new, :params => {:project_id => 1} |
|
96 |
assert_response :success |
|
97 |
assert_select 'select[name=?]', 'time_entry[activity_id]' do |
|
98 |
assert_select 'option[selected=selected]', :text => 'Design' |
|
99 |
end |
|
100 |
end |
|
101 | ||
102 |
def test_new_should_select_default_global_activity_for_user_roles_without_default_activities |
|
90 | 103 |
@request.session[:user_id] = 3 |
91 | 104 |
get :new, :params => {:project_id => 1} |
92 | 105 |
assert_response :success |
test/unit/time_entry_activity_test.rb | ||
---|---|---|
124 | 124 |
assert_include activity, project.activities |
125 | 125 |
assert_include TimeEntryActivity.find(9), project.activities |
126 | 126 |
end |
127 | ||
128 |
def test_default_activity_id_without_user_and_project_should_return_global_default_activity |
|
129 |
assert_equal 10, TimeEntryActivity.default_activity_id |
|
130 |
end |
|
131 | ||
132 |
def test_default_activity_id_with_user_and_project_should_return_role_default_activity |
|
133 |
# set a default activity for Manager role |
|
134 |
manager = Role.find(1) |
|
135 |
manager.default_time_entry_activity_id = 9 |
|
136 |
manager.save |
|
137 | ||
138 |
assert_equal 9, TimeEntryActivity.default_activity_id(User.find(2), Project.find(1)) |
|
139 |
end |
|
140 | ||
141 |
def test_default_activity_id_with_user_and_project_should_consider_role_position |
|
142 |
project = Project.find(1) |
|
143 |
user = User.find(2) |
|
144 | ||
145 |
# set a default activity for Manager role |
|
146 |
manager = Role.find(1) |
|
147 |
manager.default_time_entry_activity_id = 9 |
|
148 |
manager.save! |
|
149 | ||
150 |
# set a default activity for Developer role |
|
151 |
# and set the role position first |
|
152 |
developer = Role.find(2) |
|
153 |
developer.default_time_entry_activity_id = 11 |
|
154 |
developer.position = 1 |
|
155 |
developer.save! |
|
156 | ||
157 |
member = Member.find_or_new(project, user) |
|
158 |
member.role_ids = [1, 2] |
|
159 |
member.save! |
|
160 | ||
161 |
assert_equal 11, TimeEntryActivity.default_activity_id(user, project) |
|
162 |
end |
|
163 | ||
164 | ||
165 |
def test_default_activity_id_should_include_only_allowed_activities |
|
166 |
# set a default activity for Manager role |
|
167 |
manager = Role.find(1) |
|
168 |
manager.default_time_entry_activity_id = 9 |
|
169 |
manager.save! |
|
170 | ||
171 |
project = Project.find(1) |
|
172 | ||
173 |
# disable role default activity |
|
174 |
disable_activity = TimeEntryActivity.new({:name => "QA", :project => project, :parent => TimeEntryActivity.find(9), :active => false}) |
|
175 |
disable_activity.save! |
|
176 | ||
177 |
assert_equal 10, TimeEntryActivity.default_activity_id(User.find(2), project) |
|
178 |
end |
|
127 | 179 |
end |