Feature #3088 » 3088-v4.patch
| app/controllers/projects_controller.rb | ||
|---|---|---|
| 189 | 189 | |
| 190 | 190 |
if User.current.allowed_to_view_all_time_entries?(@project) |
| 191 | 191 |
@total_hours = TimeEntry.visible.where(cond).sum(:hours).to_f |
| 192 |
end |
|
| 193 |
if User.current.allowed_to?(:view_estimated_hours, @project) |
|
| 192 | 194 |
@total_estimated_hours = Issue.visible.where(cond).sum(:estimated_hours).to_f |
| 193 | 195 |
end |
| 194 | 196 | |
| app/models/issue.rb | ||
|---|---|---|
| 490 | 490 |
'start_date', |
| 491 | 491 |
'due_date', |
| 492 | 492 |
'done_ratio', |
| 493 |
'estimated_hours', |
|
| 494 | 493 |
'custom_field_values', |
| 495 | 494 |
'custom_fields', |
| 496 | 495 |
'lock_version', |
| ... | ... | |
| 520 | 519 |
'deleted_attachment_ids', |
| 521 | 520 |
:if => lambda {|issue, user| issue.attachments_deletable?(user)})
|
| 522 | 521 | |
| 522 |
safe_attributes 'estimated_hours', |
|
| 523 |
:if => lambda {|issue, user| user.allowed_to?(:view_estimated_hours, issue.project)}
|
|
| 524 | ||
| 523 | 525 |
def safe_attribute_names(user=nil) |
| 524 | 526 |
names = super |
| 525 | 527 |
names -= disabled_core_fields |
| app/models/issue_query.rb | ||
|---|---|---|
| 47 | 47 |
:groupable => true), |
| 48 | 48 |
QueryColumn.new(:start_date, :sortable => "#{Issue.table_name}.start_date", :groupable => true),
|
| 49 | 49 |
QueryColumn.new(:due_date, :sortable => "#{Issue.table_name}.due_date", :groupable => true),
|
| 50 |
QueryColumn.new(:estimated_hours, :sortable => "#{Issue.table_name}.estimated_hours",
|
|
| 51 |
:totalable => true), |
|
| 52 |
QueryColumn.new( |
|
| 53 |
:total_estimated_hours, |
|
| 54 |
:sortable => |
|
| 55 |
lambda do |
|
| 56 |
"COALESCE((SELECT SUM(estimated_hours) FROM #{Issue.table_name} subtasks" \
|
|
| 57 |
" WHERE #{Issue.visible_condition(User.current).gsub(/\bissues\b/, 'subtasks')}" \
|
|
| 58 |
" AND subtasks.root_id = #{Issue.table_name}.root_id" \
|
|
| 59 |
" AND subtasks.lft >= #{Issue.table_name}.lft" \
|
|
| 60 |
" AND subtasks.rgt <= #{Issue.table_name}.rgt), 0)"
|
|
| 61 |
end, |
|
| 62 |
:default_order => 'desc'), |
|
| 63 | 50 |
QueryColumn.new(:done_ratio, :sortable => "#{Issue.table_name}.done_ratio", :groupable => true),
|
| 64 | 51 |
TimestampQueryColumn.new(:created_on, :sortable => "#{Issue.table_name}.created_on",
|
| 65 | 52 |
:default_order => 'desc', :groupable => true), |
| ... | ... | |
| 205 | 192 |
add_available_filter "closed_on", :type => :date_past |
| 206 | 193 |
add_available_filter "start_date", :type => :date |
| 207 | 194 |
add_available_filter "due_date", :type => :date |
| 208 |
add_available_filter "estimated_hours", :type => :float |
|
| 209 | ||
| 210 |
if User.current.allowed_to?(:view_time_entries, project, :global => true) |
|
| 211 |
add_available_filter "spent_time", :type => :float, :label => :label_spent_time |
|
| 195 |
if User.current.allowed_to?(:view_estimated_hours, nil, :global => true) |
|
| 196 |
add_available_filter "estimated_hours", :type => :float |
|
| 212 | 197 |
end |
| 213 | ||
| 214 | 198 |
add_available_filter "done_ratio", :type => :integer |
| 215 | 199 | |
| 216 | 200 |
if User.current.allowed_to?(:set_issues_private, nil, :global => true) || |
| ... | ... | |
| 283 | 267 |
@available_columns = self.class.available_columns.dup |
| 284 | 268 |
@available_columns += issue_custom_fields.visible.collect {|cf| QueryCustomFieldColumn.new(cf)}
|
| 285 | 269 | |
| 270 |
if User.current.allowed_to?(:view_estimated_hours, project, :global => true) |
|
| 271 |
# insert the columns after due_date or at the end |
|
| 272 |
index = @available_columns.rindex {|column| column.name == :due_date}
|
|
| 273 |
index = (index ? index + 1 : -1) |
|
| 274 | ||
| 275 |
@available_columns.insert index, QueryColumn.new(:estimated_hours, |
|
| 276 |
:sortable => "#{Issue.table_name}.estimated_hours",
|
|
| 277 |
:totalable => true |
|
| 278 |
) |
|
| 279 |
index = (index.negative? ? index : index + 1) |
|
| 280 |
@available_columns.insert index, QueryColumn.new(:total_estimated_hours, |
|
| 281 |
:sortable => -> {
|
|
| 282 |
"COALESCE((SELECT SUM(estimated_hours) FROM #{Issue.table_name} subtasks" \
|
|
| 283 |
" WHERE #{Issue.visible_condition(User.current).gsub(/\bissues\b/, 'subtasks')} AND" \
|
|
| 284 |
" subtasks.root_id = #{Issue.table_name}.root_id AND" \
|
|
| 285 |
" subtasks.lft >= #{Issue.table_name}.lft AND subtasks.rgt <= #{Issue.table_name}.rgt), 0)"
|
|
| 286 |
}, |
|
| 287 |
:default_order => 'desc' |
|
| 288 |
) |
|
| 289 |
end |
|
| 290 | ||
| 286 | 291 |
if User.current.allowed_to?(:view_time_entries, project, :global => true) |
| 287 |
# insert the columns after total_estimated_hours or at the end |
|
| 288 |
index = @available_columns.find_index {|column| column.name == :total_estimated_hours}
|
|
| 292 |
# insert the columns after total_estimated_hours or the columns after due_date or at the end
|
|
| 293 |
index = @available_columns.rindex {|column| column.name == :total_estimated_hours || column.name == :due_date }
|
|
| 289 | 294 |
index = (index ? index + 1 : -1) |
| 290 | 295 | |
| 291 | 296 |
subselect = "SELECT SUM(hours) FROM #{TimeEntry.table_name}" +
|
| ... | ... | |
| 307 | 312 |
" WHERE (#{TimeEntry.visible_condition(User.current)})" +
|
| 308 | 313 |
" AND subtasks.root_id = #{Issue.table_name}.root_id AND subtasks.lft >= #{Issue.table_name}.lft AND subtasks.rgt <= #{Issue.table_name}.rgt"
|
| 309 | 314 | |
| 315 |
index = (index.negative? ? index : index + 1) |
|
| 310 | 316 |
@available_columns.insert( |
| 311 |
index + 1,
|
|
| 317 |
index, |
|
| 312 | 318 |
QueryColumn.new(:total_spent_hours, |
| 313 | 319 |
:sortable => "COALESCE((#{subselect}), 0)",
|
| 314 | 320 |
:default_order => 'desc', |
| app/models/journal.rb | ||
|---|---|---|
| 111 | 111 |
detail.custom_field && detail.custom_field.visible_by?(project, user) |
| 112 | 112 |
elsif detail.property == 'relation' |
| 113 | 113 |
Issue.find_by_id(detail.value || detail.old_value).try(:visible?, user) |
| 114 |
elsif detail.property == 'attr' && detail.prop_key == 'estimated_hours' |
|
| 115 |
user.allowed_to?(:view_estimated_hours, project) |
|
| 114 | 116 |
else |
| 115 | 117 |
true |
| 116 | 118 |
end |
| app/views/issues/show.api.rsb | ||
|---|---|---|
| 16 | 16 |
api.due_date @issue.due_date |
| 17 | 17 |
api.done_ratio @issue.done_ratio |
| 18 | 18 |
api.is_private @issue.is_private |
| 19 |
api.estimated_hours @issue.estimated_hours |
|
| 20 |
api.total_estimated_hours @issue.total_estimated_hours |
|
| 19 |
if User.current.allowed_to?(:view_estimated_hours, @project) |
|
| 20 |
api.estimated_hours @issue.estimated_hours |
|
| 21 |
api.total_estimated_hours @issue.total_estimated_hours |
|
| 22 |
end |
|
| 21 | 23 |
if User.current.allowed_to?(:view_time_entries, @project) |
| 22 | 24 |
api.spent_hours(@issue.spent_hours) |
| 23 | 25 |
api.total_spent_hours(@issue.total_spent_hours) |
| app/views/issues/show.html.erb | ||
|---|---|---|
| 68 | 68 |
unless @issue.disabled_core_fields.include?('done_ratio')
|
| 69 | 69 |
rows.right l(:field_done_ratio), progress_bar(@issue.done_ratio, :legend => "#{@issue.done_ratio}%"), :class => 'progress'
|
| 70 | 70 |
end |
| 71 |
unless @issue.disabled_core_fields.include?('estimated_hours')
|
|
| 71 |
if User.current.allowed_to?(:view_estimated_hours, @project) && !@issue.disabled_core_fields.include?('estimated_hours')
|
|
| 72 | 72 |
rows.right l(:field_estimated_hours), issue_estimated_hours_details(@issue), :class => 'estimated-hours' |
| 73 | 73 |
end |
| 74 | 74 |
if User.current.allowed_to?(:view_time_entries, @project) && @issue.total_spent_hours > 0 |
| app/views/projects/show.html.erb | ||
|---|---|---|
| 97 | 97 |
</div> |
| 98 | 98 |
<% end %> |
| 99 | 99 | |
| 100 |
<% if User.current.allowed_to?(:view_time_entries, @project) %> |
|
| 100 |
<% allowed_to_view_time_entries, allowed_to_view_estimated_hours = User.current.allowed_to?(:view_time_entries, @project), User.current.allowed_to?(:view_estimated_hours, @project) %> |
|
| 101 |
<% if allowed_to_view_time_entries || allowed_to_view_estimated_hours %> |
|
| 101 | 102 |
<div class="spent_time box"> |
| 102 | 103 |
<h3 class="icon icon-time"><%= l(:label_time_tracking) %></h3> |
| 103 | 104 |
<ul> |
| 104 |
<% if @total_estimated_hours.present? %>
|
|
| 105 |
<li><%= l(:field_estimated_hours) %>: <%= l_hours(@total_estimated_hours) %>
|
|
| 106 |
<% end %>
|
|
| 107 |
<% if @total_hours.present? %>
|
|
| 108 |
<li><%= l(:label_spent_time) %>: <%= l_hours(@total_hours) %>
|
|
| 109 |
<% end %>
|
|
| 105 |
<% if @total_estimated_hours.present? && allowed_to_view_estimated_hours %>
|
|
| 106 |
<li><%= l(:field_estimated_hours) %>: <%= l_hours(@total_estimated_hours) %> |
|
| 107 |
<% end %> |
|
| 108 |
<% if @total_hours.present? && allowed_to_view_time_entries %>
|
|
| 109 |
<li><%= l(:label_spent_time) %>: <%= l_hours(@total_hours) %> |
|
| 110 |
<% end %> |
|
| 110 | 111 |
</ul> |
| 112 |
<% if allowed_to_view_time_entries %> |
|
| 111 | 113 |
<p> |
| 112 |
<% if User.current.allowed_to?(:log_time, @project) %> |
|
| 114 |
<% if User.current.allowed_to?(:log_time, @project) %>
|
|
| 113 | 115 |
<%= link_to l(:button_log_time), new_project_time_entry_path(@project) %> | |
| 114 |
<% end %> |
|
| 116 |
<% end %>
|
|
| 115 | 117 |
<%= link_to(l(:label_details), project_time_entries_path(@project)) %> | |
| 116 | 118 |
<%= link_to(l(:label_report), report_project_time_entries_path(@project)) %> |
| 117 | 119 |
</p> |
| 120 |
<% end %> |
|
| 118 | 121 |
</div> |
| 119 |
<% end %> |
|
| 122 |
<% end %>
|
|
| 120 | 123 |
<%= call_hook(:view_projects_show_left, :project => @project) %> |
| 121 | 124 |
</div> |
| 122 | 125 | |
| ... | ... | |
| 137 | 140 |
<ul class="subprojects"> |
| 138 | 141 |
<% @subprojects.each do |project| %> |
| 139 | 142 |
<li><%= link_to(project.name, project_path(project), :class => project.css_classes).html_safe %></li> |
| 140 |
<% end %>
|
|
| 143 |
<% end %> |
|
| 141 | 144 |
</ul> |
| 142 | 145 |
</div> |
| 143 | 146 |
<% end %> |
| app/views/versions/show.html.erb | ||
|---|---|---|
| 14 | 14 |
<%= render(:partial => "wiki/content", :locals => {:content => @version.wiki_page.content}) if @version.wiki_page %>
|
| 15 | 15 | |
| 16 | 16 |
<div id="version-summary"> |
| 17 |
<% if @version.visible_fixed_issues.estimated_hours > 0 || User.current.allowed_to?(:view_time_entries, @project) %> |
|
| 17 |
<% allowed_to_view_all_time_entries, allowed_to_view_estimated_hours = User.current.allowed_to_view_all_time_entries?(@project), User.current.allowed_to?(:view_estimated_hours, @project) %> |
|
| 18 |
<% if (@version.visible_fixed_issues.estimated_hours > 0 && allowed_to_view_estimated_hours) || allowed_to_view_all_time_entries %> |
|
| 18 | 19 |
<fieldset class="time-tracking"><legend><%= l(:label_time_tracking) %></legend> |
| 19 | 20 |
<table> |
| 21 |
<% if allowed_to_view_estimated_hours %> |
|
| 20 | 22 |
<tr> |
| 21 | 23 |
<th><%= l(:field_estimated_hours) %></th> |
| 22 | 24 |
<td class="total-hours"><%= link_to html_hours(l_hours(@version.visible_fixed_issues.estimated_hours)), |
| 23 | 25 |
project_issues_path(@version.project, :set_filter => 1, :status_id => '*', :fixed_version_id => @version.id, :c => [:tracker, :status, :subject, :estimated_hours], :t => [:estimated_hours]) %></td> |
| 24 | 26 |
</tr> |
| 25 |
<% if User.current.allowed_to_view_all_time_entries?(@project) %> |
|
| 27 |
<% end %> |
|
| 28 |
<% if allowed_to_view_all_time_entries %> |
|
| 26 | 29 |
<tr> |
| 27 | 30 |
<th><%= l(:label_spent_time) %></th> |
| 28 | 31 |
<td class="total-hours"><%= link_to html_hours(l_hours(@version.spent_hours)), |
| config/locales/en.yml | ||
|---|---|---|
| 548 | 548 |
permission_delete_issue_watchers: Delete watchers |
| 549 | 549 |
permission_log_time: Log spent time |
| 550 | 550 |
permission_view_time_entries: View spent time |
| 551 |
permission_view_estimated_hours: View estimated time |
|
| 551 | 552 |
permission_edit_time_entries: Edit time logs |
| 552 | 553 |
permission_edit_own_time_entries: Edit own time logs |
| 553 | 554 |
permission_view_news: View news |
| db/migrate/20220729101502_add_view_estimated_hours_to_all_existing_roles.rb | ||
|---|---|---|
| 1 |
class AddViewEstimatedHoursToAllExistingRoles < ActiveRecord::Migration[6.1] |
|
| 2 |
def up |
|
| 3 |
Role.all.each { |role| role.add_permission! :view_estimated_hours }
|
|
| 4 |
end |
|
| 5 | ||
| 6 |
def down |
|
| 7 |
Role.all.each { |role| role.remove_permission! :view_estimated_hours }
|
|
| 8 |
end |
|
| 9 |
end |
|
| lib/redmine/default_data/loader.rb | ||
|---|---|---|
| 71 | 71 |
:view_calendar, |
| 72 | 72 |
:log_time, |
| 73 | 73 |
:view_time_entries, |
| 74 |
:view_estimated_hours, |
|
| 74 | 75 |
:view_news, |
| 75 | 76 |
:comment_news, |
| 76 | 77 |
:view_documents, |
| ... | ... | |
| 102 | 103 |
:view_calendar, |
| 103 | 104 |
:log_time, |
| 104 | 105 |
:view_time_entries, |
| 106 |
:view_estimated_hours, |
|
| 105 | 107 |
:view_news, |
| 106 | 108 |
:comment_news, |
| 107 | 109 |
:view_documents, |
| ... | ... | |
| 122 | 124 |
:view_gantt, |
| 123 | 125 |
:view_calendar, |
| 124 | 126 |
:view_time_entries, |
| 127 |
:view_estimated_hours, |
|
| 125 | 128 |
:view_news, |
| 126 | 129 |
:comment_news, |
| 127 | 130 |
:view_documents, |
| ... | ... | |
| 137 | 140 |
:view_gantt, |
| 138 | 141 |
:view_calendar, |
| 139 | 142 |
:view_time_entries, |
| 143 |
:view_estimated_hours, |
|
| 140 | 144 |
:view_news, |
| 141 | 145 |
:view_documents, |
| 142 | 146 |
:view_wiki_pages, |
| lib/redmine/export/pdf/issues_pdf_helper.rb | ||
|---|---|---|
| 57 | 57 |
right << [l(:field_start_date), format_date(issue.start_date)] unless issue.disabled_core_fields.include?('start_date')
|
| 58 | 58 |
right << [l(:field_due_date), format_date(issue.due_date)] unless issue.disabled_core_fields.include?('due_date')
|
| 59 | 59 |
right << [l(:field_done_ratio), "#{issue.done_ratio}%"] unless issue.disabled_core_fields.include?('done_ratio')
|
| 60 |
right << [l(:field_estimated_hours), l_hours(issue.estimated_hours)] unless issue.disabled_core_fields.include?('estimated_hours')
|
|
| 60 |
right << [l(:field_estimated_hours), l_hours(issue.estimated_hours)] if \ |
|
| 61 |
User.current.allowed_to?(:view_estimated_hours, issue.project) && !issue.disabled_core_fields.include?('estimated_hours')
|
|
| 61 | 62 |
right << [l(:label_spent_time), l_hours(issue.total_spent_hours)] if User.current.allowed_to?(:view_time_entries, issue.project) |
| 62 | 63 | |
| 63 | 64 |
rows = left.size > right.size ? left.size : right.size |
| lib/redmine/preparation.rb | ||
|---|---|---|
| 84 | 84 | |
| 85 | 85 |
map.project_module :time_tracking do |map| |
| 86 | 86 |
map.permission :view_time_entries, {:timelog => [:index, :report, :show]}, :read => true
|
| 87 |
map.permission :view_estimated_hours, {}, :read => true
|
|
| 87 | 88 |
map.permission :log_time, {:timelog => [:new, :create]}, :require => :loggedin
|
| 88 | 89 |
map.permission :edit_time_entries, |
| 89 | 90 |
{:timelog => [:edit, :update, :destroy, :bulk_edit, :bulk_update]},
|
| test/fixtures/roles.yml | ||
|---|---|---|
| 35 | 35 |
- :view_calendar |
| 36 | 36 |
- :log_time |
| 37 | 37 |
- :view_time_entries |
| 38 |
- :view_estimated_hours |
|
| 38 | 39 |
- :edit_time_entries |
| 39 | 40 |
- :delete_time_entries |
| 40 | 41 |
- :import_time_entries |
| ... | ... | |
| 102 | 103 |
- :view_calendar |
| 103 | 104 |
- :log_time |
| 104 | 105 |
- :view_time_entries |
| 106 |
- :view_estimated_hours |
|
| 105 | 107 |
- :edit_own_time_entries |
| 106 | 108 |
- :view_news |
| 107 | 109 |
- :manage_news |
| ... | ... | |
| 151 | 153 |
- :view_calendar |
| 152 | 154 |
- :log_time |
| 153 | 155 |
- :view_time_entries |
| 156 |
- :view_estimated_hours |
|
| 154 | 157 |
- :view_news |
| 155 | 158 |
- :manage_news |
| 156 | 159 |
- :comment_news |
| ... | ... | |
| 191 | 194 |
- :view_calendar |
| 192 | 195 |
- :log_time |
| 193 | 196 |
- :view_time_entries |
| 197 |
- :view_estimated_hours |
|
| 194 | 198 |
- :view_news |
| 195 | 199 |
- :comment_news |
| 196 | 200 |
- :view_documents |
| ... | ... | |
| 218 | 222 |
- :view_gantt |
| 219 | 223 |
- :view_calendar |
| 220 | 224 |
- :view_time_entries |
| 225 |
- :view_estimated_hours |
|
| 221 | 226 |
- :view_news |
| 222 | 227 |
- :view_documents |
| 223 | 228 |
- :view_wiki_pages |
| test/functional/issues_controller_test.rb | ||
|---|---|---|
| 1581 | 1581 |
assert_select 'table.issues td.total_estimated_hours' |
| 1582 | 1582 |
end |
| 1583 | 1583 | |
| 1584 |
def test_index_should_not_show_estimated_hours_column_without_permission |
|
| 1585 |
Role.anonymous.remove_permission! :view_estimated_hours |
|
| 1586 |
get( |
|
| 1587 |
:index, |
|
| 1588 |
:params => {
|
|
| 1589 |
:set_filter => 1, |
|
| 1590 |
:c => %w(subject estimated_hours) |
|
| 1591 |
} |
|
| 1592 |
) |
|
| 1593 |
assert_select 'td.estimated_hours', 0 |
|
| 1594 |
end |
|
| 1595 | ||
| 1584 | 1596 |
def test_index_should_not_show_spent_hours_column_without_permission |
| 1585 | 1597 |
Role.anonymous.remove_permission! :view_time_entries |
| 1586 | 1598 |
get( |
| test/functional/projects_controller_test.rb | ||
|---|---|---|
| 837 | 837 |
end |
| 838 | 838 |
end |
| 839 | 839 | |
| 840 |
def test_show_by_non_admin_user_with_view_estimated_hours_permission_should_show_estimated_time |
|
| 841 |
@request.session[:user_id] = 2 # manager |
|
| 842 |
get(:show, :params => {:id => 'ecookbook'})
|
|
| 843 | ||
| 844 |
assert_select 'div.spent_time.box>ul' do |
|
| 845 |
assert_select '>li', :text => 'Estimated time: 203:30 hours' |
|
| 846 |
end |
|
| 847 |
end |
|
| 848 | ||
| 849 |
def test_show_by_non_admin_user_without_view_estimated_hours_permission_should_not_show_estimated_time |
|
| 850 |
Role.find_by(name: 'Manager').remove_permission! :view_estimated_hours |
|
| 851 |
@request.session[:user_id] = 2 # manager |
|
| 852 |
get(:show, :params => {:id => 'ecookbook'})
|
|
| 853 | ||
| 854 |
assert_select 'div.spent_time.box>ul' do |
|
| 855 |
assert_select '>li', :text => 'Estimated time: 203.50 hours', :count => 0 |
|
| 856 |
end |
|
| 857 |
end |
|
| 858 | ||
| 840 | 859 |
def test_settings |
| 841 | 860 |
@request.session[:user_id] = 2 # manager |
| 842 | 861 |
get(:settings, :params => {:id => 1})
|
| test/functional/versions_controller_test.rb | ||
|---|---|---|
| 165 | 165 |
assert_select 'a', :text => '1 open' |
| 166 | 166 |
end |
| 167 | 167 | |
| 168 |
assert_select '.time-tracking td.total-hours a:first-child', :text => '2:00 hours' |
|
| 168 |
assert_select '.time-tracking tr:first-child' do |
|
| 169 |
assert_select 'th', :text => 'Estimated time' |
|
| 170 |
assert_select 'td.total-hours a', :text => '2:00 hours' |
|
| 171 |
end |
|
| 172 | ||
| 173 |
Role.non_member.remove_permission! :view_estimated_hours |
|
| 174 | ||
| 175 |
get :show, :params => {:id => 4}
|
|
| 176 |
assert_response :success |
|
| 177 | ||
| 178 |
assert_select 'p.progress-info' do |
|
| 179 |
assert_select 'a', :text => '1 issue' |
|
| 180 |
assert_select 'a', :text => '1 open' |
|
| 181 |
end |
|
| 182 | ||
| 183 |
assert_select '.time-tracking th', :text => 'Estimated time', :count => 0 |
|
| 169 | 184 |
end |
| 170 | 185 | |
| 171 | 186 |
def test_show_should_link_to_spent_time_on_version |
| test/integration/api_test/issues_test.rb | ||
|---|---|---|
| 489 | 489 |
end |
| 490 | 490 |
end |
| 491 | 491 | |
| 492 |
test "GET /issues/:id.xml should contains total_spent_hours, and should not contains estimated_hours and total_estimated_hours when permission does not exists" do |
|
| 493 |
parent = Issue.find(3) |
|
| 494 |
parent.update_columns :estimated_hours => 2.0 |
|
| 495 |
child = Issue.generate!(:parent_issue_id => parent.id, :estimated_hours => 3.0) |
|
| 496 |
TimeEntry.create!(:project => child.project, :issue => child, :user => child.author, :spent_on => child.author.today, |
|
| 497 |
:hours => '2.5', :comments => '', :activity_id => TimeEntryActivity.first.id) |
|
| 498 |
# remove permission! |
|
| 499 |
Role.anonymous.remove_permission! :view_estimated_hours |
|
| 500 | ||
| 501 |
get '/issues/3.xml' |
|
| 502 | ||
| 503 |
assert_equal 'application/xml; charset=utf-8', response.content_type |
|
| 504 |
assert_select 'issue' do |
|
| 505 |
assert_select 'estimated_hours', false |
|
| 506 |
assert_select 'total_estimated_hours', false |
|
| 507 |
assert_select 'spent_hours', parent.spent_hours.to_s |
|
| 508 |
assert_select 'total_spent_hours', (parent.spent_hours.to_f + 2.5).to_s |
|
| 509 |
end |
|
| 510 |
end |
|
| 511 | ||
| 492 | 512 |
test "GET /issues/:id.xml should contains visible spent_hours only" do |
| 493 | 513 |
user = User.find_by_login('jsmith')
|
| 494 | 514 |
Role.find(1).update(:time_entries_visibility => 'own') |
| ... | ... | |
| 537 | 557 |
assert_nil json['issue']['total_spent_hours'] |
| 538 | 558 |
end |
| 539 | 559 | |
| 560 |
test "GET /issues/:id.json should contains total_spent_hours, and should not contains estimated_hours and total_estimated_hours when permission does not exists" do |
|
| 561 |
parent = Issue.find(3) |
|
| 562 |
parent.update_columns :estimated_hours => 2.0 |
|
| 563 |
child = Issue.generate!(:parent_issue_id => parent.id, :estimated_hours => 3.0) |
|
| 564 |
TimeEntry.create!(:project => child.project, :issue => child, :user => child.author, :spent_on => child.author.today, |
|
| 565 |
:hours => '2.5', :comments => '', :activity_id => TimeEntryActivity.first.id) |
|
| 566 |
# remove permission! |
|
| 567 |
Role.anonymous.remove_permission! :view_estimated_hours |
|
| 568 | ||
| 569 |
get '/issues/3.json' |
|
| 570 | ||
| 571 |
assert_equal 'application/json; charset=utf-8', response.content_type |
|
| 572 |
json = ActiveSupport::JSON.decode(response.body) |
|
| 573 |
assert_nil json['issue']['estimated_hours'] |
|
| 574 |
assert_nil json['issue']['total_estimated_hours'] |
|
| 575 |
assert_equal parent.spent_hours, json['issue']['spent_hours'] |
|
| 576 |
assert_equal (parent.spent_hours.to_f + 2.5), json['issue']['total_spent_hours'] |
|
| 577 |
end |
|
| 578 | ||
| 540 | 579 |
test "GET /issues/:id.json should contains visible spent_hours only" do |
| 541 | 580 |
user = User.find_by_login('jsmith')
|
| 542 | 581 |
Role.find(1).update(:time_entries_visibility => 'own') |
| test/unit/journal_test.rb | ||
|---|---|---|
| 245 | 245 |
assert_equal 2, visible_details.size |
| 246 | 246 |
end |
| 247 | 247 | |
| 248 |
def test_visible_details_should_have_privilege_to_view_estimated_hours |
|
| 249 |
journal = Journal.generate! do |j| |
|
| 250 |
j.details << |
|
| 251 |
JournalDetail.new(:property => 'attr', :prop_key => 'estimated_hours', :old_value => '200.00', :value => '100.00') |
|
| 252 |
end |
|
| 253 |
project = journal.journalized.project |
|
| 254 | ||
| 255 |
user = User.find(2) |
|
| 256 |
assert user.allowed_to?(:view_estimated_hours, project) |
|
| 257 |
visible_details = journal.visible_details(user) |
|
| 258 |
assert_equal 1, visible_details.size |
|
| 259 |
detail = visible_details.first |
|
| 260 |
assert_equal 'attr', detail.property |
|
| 261 |
assert_equal 'estimated_hours', detail.prop_key |
|
| 262 |
assert_equal '200.00', detail.old_value |
|
| 263 |
assert_equal '100.00', detail.value |
|
| 264 | ||
| 265 |
Role.anonymous.remove_permission!(:view_estimated_hours) |
|
| 266 |
assert !User.anonymous.allowed_to?(:view_estimated_hours, project) |
|
| 267 |
visible_details = journal.visible_details(User.anonymous) |
|
| 268 |
assert_equal 0, visible_details.size |
|
| 269 |
end |
|
| 270 | ||
| 248 | 271 |
def test_attachments |
| 249 | 272 |
journal = Journal.new |
| 250 | 273 |
[0, 1].map{ |i| Attachment.generate!(:file => mock_file_with_options(:original_filename => "image#{i}.png")) }.each do |attachment|
|
| test/unit/mail_handler_test.rb | ||
|---|---|---|
| 43 | 43 |
end |
| 44 | 44 | |
| 45 | 45 |
def test_add_issue_with_specific_overrides |
| 46 |
project = Project.find_by(name: 'OnlineStore') |
|
| 47 |
project.enabled_module_names += [:time_tracking] |
|
| 48 |
project.save! |
|
| 49 | ||
| 46 | 50 |
issue = |
| 47 | 51 |
submit_email( |
| 48 | 52 |
'ticket_on_given_project.eml', |
| ... | ... | |
| 74 | 78 |
end |
| 75 | 79 | |
| 76 | 80 |
def test_add_issue_with_all_overrides |
| 81 |
project = Project.find_by_name('OnlineStore')
|
|
| 82 |
project.enabled_module_names += [:time_tracking] |
|
| 83 |
project.save! |
|
| 84 | ||
| 77 | 85 |
issue = submit_email('ticket_on_given_project.eml', :allow_override => 'all')
|
| 78 | 86 |
assert issue.is_a?(Issue) |
| 79 | 87 |
assert !issue.new_record? |
- « Previous
- 1
- …
- 4
- 5
- 6
- Next »