Feature #29286 » 0001-Option-to-set-default-time-entry-activity-per-role-r21737.patch
| app/helpers/timelog_helper.rb | ||
|---|---|---|
| 48 | 48 |
principals_options_for_select(collection, time_entry.user_id.to_s) |
| 49 | 49 |
end |
| 50 | 50 | |
| 51 |
def default_activity(time_entry) |
|
| 52 |
if @project |
|
| 53 |
time_entry.activity_id |
|
| 54 |
else |
|
| 55 |
TimeEntryActivity.default_activity_id(User.current, time_entry.project) |
|
| 56 |
end |
|
| 57 |
end |
|
| 58 | ||
| 51 | 59 |
def select_hours(data, criteria, value) |
| 52 | 60 |
if value.to_s.empty? |
| 53 | 61 |
data.select {|row| row[criteria].blank?}
|
| app/models/role.rb | ||
|---|---|---|
| 60 | 60 |
where("#{compare} builtin = 0")
|
| 61 | 61 |
end) |
| 62 | 62 | |
| 63 |
belongs_to :default_time_entry_activity, :class_name => "TimeEntryActivity" |
|
| 64 | ||
| 63 | 65 |
before_destroy :check_deletable |
| 64 | 66 |
has_many :workflow_rules, :dependent => :delete_all |
| 65 | 67 |
has_and_belongs_to_many :custom_fields, :join_table => "#{table_name_prefix}custom_fields_roles#{table_name_suffix}", :foreign_key => "role_id"
|
| ... | ... | |
| 104 | 106 |
'managed_role_ids', |
| 105 | 107 |
'permissions', |
| 106 | 108 |
'permissions_all_trackers', |
| 107 |
'permissions_tracker_ids' |
|
| 109 |
'permissions_tracker_ids', |
|
| 110 |
'default_time_entry_activity_id' |
|
| 108 | 111 |
) |
| 109 | 112 | |
| 110 | 113 |
# Copies attributes from another role, arg can be an id or a Role |
| app/models/time_entry.rb | ||
|---|---|---|
| 107 | 107 |
def initialize(attributes=nil, *args) |
| 108 | 108 |
super |
| 109 | 109 |
if new_record? && self.activity.nil? |
| 110 |
if default_activity = TimeEntryActivity.default(self.project) |
|
| 111 |
self.activity_id = default_activity.id |
|
| 112 |
elsif (activities = TimeEntryActivity.available_activities(self.project)) && activities.count == 1 |
|
| 113 |
self.activity_id = activities.first.id |
|
| 114 |
end |
|
| 110 |
self.activity_id = TimeEntryActivity.default_activity_id(User.current, self.project) |
|
| 115 | 111 |
self.hours = nil if hours == 0 |
| 116 | 112 |
end |
| 117 | 113 |
end |
| app/models/time_entry_activity.rb | ||
|---|---|---|
| 32 | 32 |
project.activities.detect { |activity| activity.parent_id == default_activity.id }
|
| 33 | 33 |
end |
| 34 | 34 | |
| 35 |
# Returns the available activities for the time entry |
|
| 35 | 36 |
def self.available_activities(project=nil) |
| 36 | 37 |
if project.nil? |
| 37 | 38 |
TimeEntryActivity.shared.active |
| ... | ... | |
| 55 | 56 |
def transfer_relations(to) |
| 56 | 57 |
objects.update_all(:activity_id => to.id) |
| 57 | 58 |
end |
| 59 | ||
| 60 |
def self.default_activity_id(user=nil, project=nil) |
|
| 61 |
default_activities = [] |
|
| 62 |
default_activity = nil |
|
| 63 |
available_activities = self.available_activities(project) |
|
| 64 | ||
| 65 |
if project && user |
|
| 66 |
user_membership = user.membership(project) |
|
| 67 |
if user_membership |
|
| 68 |
default_activities = user_membership.roles.where.not(:default_time_entry_activity_id => nil).sort.pluck(:default_time_entry_activity_id) |
|
| 69 |
end |
|
| 70 | ||
| 71 |
project_default_activity = self.default(project) |
|
| 72 |
if project_default_activity |
|
| 73 |
default_activities << project_default_activity.id unless default_activities.include?(project_default_activity.id) |
|
| 74 |
end |
|
| 75 |
end |
|
| 76 | ||
| 77 |
global_activity = self.default |
|
| 78 |
if global_activity |
|
| 79 |
default_activities << global_activity.id unless default_activities.include?(global_activity.id) |
|
| 80 |
end |
|
| 81 | ||
| 82 |
if available_activities.count == 1 |
|
| 83 |
default_activities << available_activities.first.id unless default_activities.include?(available_activities.first.id) |
|
| 84 |
end |
|
| 85 | ||
| 86 |
default_activities.each do |id| |
|
| 87 |
default_activity = available_activities.detect{ |a| a.id == id || a.parent_id == id }
|
|
| 88 |
break unless default_activity.nil? |
|
| 89 |
end |
|
| 90 | ||
| 91 |
default_activity.id unless default_activity.nil? |
|
| 92 |
end |
|
| 58 | 93 |
end |
| app/views/roles/_form.html.erb | ||
|---|---|---|
| 39 | 39 |
</p> |
| 40 | 40 |
<% end %> |
| 41 | 41 | |
| 42 |
<% unless @role.anonymous? %> |
|
| 43 |
<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> |
|
| 44 |
<% end %> |
|
| 45 | ||
| 42 | 46 |
<% if @role.new_record? && @roles.any? %> |
| 43 | 47 |
<p><label for="copy_workflow_from"><%= l(:label_copy_workflow_from) %></label> |
| 44 | 48 |
<%= 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 | ||
|---|---|---|
| 89 | 89 |
assert_response 403 |
| 90 | 90 |
end |
| 91 | 91 | |
| 92 |
def test_new_should_select_default_activity |
|
| 92 |
def test_new_should_select_default_role_activity |
|
| 93 |
developer = Role.find(2) |
|
| 94 |
developer.default_time_entry_activity_id = 9 |
|
| 95 |
developer.save! |
|
| 96 | ||
| 97 |
@request.session[:user_id] = 3 |
|
| 98 |
get :new, :params => {:project_id => 1}
|
|
| 99 |
assert_response :success |
|
| 100 |
assert_select 'select[name=?]', 'time_entry[activity_id]' do |
|
| 101 |
assert_select 'option[selected=selected]', :text => 'Design' |
|
| 102 |
end |
|
| 103 |
end |
|
| 104 | ||
| 105 |
def test_new_should_select_default_global_activity_for_user_roles_without_default_activities |
|
| 93 | 106 |
@request.session[:user_id] = 3 |
| 94 | 107 |
get :new, :params => {:project_id => 1}
|
| 95 | 108 |
assert_response :success |
| test/unit/time_entry_activity_test.rb | ||
|---|---|---|
| 231 | 231 |
assert_not_equal TimeEntryActivity.default(project).id, 10 |
| 232 | 232 |
assert_equal TimeEntryActivity.default(project).id, project_specific_default_activity.id |
| 233 | 233 |
end |
| 234 | ||
| 235 |
def test_default_activity_id_without_user_and_project_should_return_global_default_activity |
|
| 236 |
assert_equal 10, TimeEntryActivity.default_activity_id |
|
| 237 |
end |
|
| 238 | ||
| 239 |
def test_default_activity_id_with_user_and_project_should_return_role_default_activity |
|
| 240 |
# set a default activity for Manager role |
|
| 241 |
manager = Role.find(1) |
|
| 242 |
manager.default_time_entry_activity_id = 9 |
|
| 243 |
manager.save |
|
| 244 | ||
| 245 |
assert_equal 9, TimeEntryActivity.default_activity_id(User.find(2), Project.find(1)) |
|
| 246 |
end |
|
| 247 | ||
| 248 |
def test_default_activity_id_with_user_and_project_should_consider_role_position |
|
| 249 |
project = Project.find(1) |
|
| 250 |
user = User.find(2) |
|
| 251 | ||
| 252 |
# set a default activity for Manager role |
|
| 253 |
manager = Role.find(1) |
|
| 254 |
manager.default_time_entry_activity_id = 9 |
|
| 255 |
manager.save! |
|
| 256 | ||
| 257 |
# set a default activity for Developer role |
|
| 258 |
# and set the role position first |
|
| 259 |
developer = Role.find(2) |
|
| 260 |
developer.default_time_entry_activity_id = 11 |
|
| 261 |
developer.position = 1 |
|
| 262 |
developer.save! |
|
| 263 | ||
| 264 |
member = Member.find_or_initialize_by(:project_id => project.id, :user_id => user.id) |
|
| 265 |
member.role_ids = [1, 2] |
|
| 266 |
member.save! |
|
| 267 | ||
| 268 |
assert_equal 11, TimeEntryActivity.default_activity_id(user, project) |
|
| 269 |
end |
|
| 270 | ||
| 271 |
def test_default_activity_id_should_include_only_available_activities |
|
| 272 |
# set a default activity for Manager role |
|
| 273 |
manager = Role.find(1) |
|
| 274 |
manager.default_time_entry_activity_id = 9 |
|
| 275 |
manager.save! |
|
| 276 | ||
| 277 |
project = Project.find(1) |
|
| 278 | ||
| 279 |
# disable role default activity |
|
| 280 |
disable_activity = TimeEntryActivity.new({:name => "QA", :project => project, :parent => TimeEntryActivity.find(9), :active => false})
|
|
| 281 |
disable_activity.save! |
|
| 282 | ||
| 283 |
assert_equal 10, TimeEntryActivity.default_activity_id(User.find(2), project) |
|
| 284 |
end |
|
| 285 | ||
| 286 |
def test_default_activity_id_should_selected_from_highest_priority_of_multiple_default_activity_candidates |
|
| 287 |
project = Project.find(1) |
|
| 288 | ||
| 289 |
manager = Role.find(1) |
|
| 290 |
manager.default_time_entry_activity_id = 9 |
|
| 291 |
manager.save |
|
| 292 | ||
| 293 |
# Returns the role_default_activity with the highest priority |
|
| 294 |
assert_equal 9, TimeEntryActivity.default_activity_id(User.find(2), project) |
|
| 295 | ||
| 296 |
# Returns the child activity of role_default_activity if there is an activity that has the id of role_default_activity as parent_id |
|
| 297 |
design_project_activity = TimeEntryActivity.create!(name: 'Design', parent_id: 9, project_id: project.id, is_default: false) |
|
| 298 |
development_project_activity = TimeEntryActivity.create!(name: 'Development', parent_id: 10, project_id: project.id, is_default: true) |
|
| 299 |
qa_project_activity = TimeEntryActivity.create!(name: 'QA', parent_id: 11, project_id: project.id, is_default: false) |
|
| 300 |
assert_equal design_project_activity.id, TimeEntryActivity.default_activity_id(User.find(2), project) |
|
| 301 | ||
| 302 |
# Returns default project activity if role_default_activity is not present |
|
| 303 |
manager.default_time_entry_activity_id = nil |
|
| 304 |
manager.save |
|
| 305 |
assert_equal development_project_activity.id, TimeEntryActivity.default_activity_id(User.find(2), project) |
|
| 306 | ||
| 307 |
# Returns global default activity if role_default_activity and project activities are not present |
|
| 308 |
[design_project_activity, development_project_activity, qa_project_activity].each {|activity| activity.destroy}
|
|
| 309 |
TimeEntryActivity.find(11).update(is_default: true) |
|
| 310 |
assert_equal 11, TimeEntryActivity.default_activity_id(User.find(2), project) |
|
| 311 | ||
| 312 |
# If there is only one activity available, it returns that activity. |
|
| 313 |
[TimeEntryActivity.find(10), TimeEntryActivity.find(11)].each {|a| a.update(active: false)}
|
|
| 314 |
assert_equal 9, TimeEntryActivity.default_activity_id(User.find(2), project) |
|
| 315 |
end |
|
| 234 | 316 |
end |
- « Previous
- 1
- 2
- 3
- Next »