[#4289] Ported the billing plugin's timesheet hooks.
This commit is contained in:
@@ -100,4 +100,9 @@ class Rate < ActiveRecord::Base
|
|||||||
raise Rate::InvalidParameterException.new("date must be a valid Date string (e.g. YYYY-MM-DD)")
|
raise Rate::InvalidParameterException.new("date must be a valid Date string (e.g. YYYY-MM-DD)")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if Rails.env.test?
|
||||||
|
public
|
||||||
|
generator_for :date_in_effect => Date.today
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -7,3 +7,4 @@ en:
|
|||||||
rate_error_user_not_found: User not found
|
rate_error_user_not_found: User not found
|
||||||
rate_label_set_rate: Set Rate
|
rate_label_set_rate: Set Rate
|
||||||
rate_label_default: Default Rate
|
rate_label_default: Default Rate
|
||||||
|
rate_cost: Cost
|
||||||
|
|||||||
2
init.rb
2
init.rb
@@ -31,7 +31,9 @@ Redmine::Plugin.register :redmine_rate do
|
|||||||
permission :view_rate, { }
|
permission :view_rate, { }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
require 'redmine_rate/hooks/timesheet_hook_helper'
|
||||||
require 'redmine_rate/hooks/plugin_timesheet_views_timesheets_time_entry_row_class_hook'
|
require 'redmine_rate/hooks/plugin_timesheet_views_timesheets_time_entry_row_class_hook'
|
||||||
require 'redmine_rate/hooks/plugin_timesheet_views_timesheet_group_header_hook'
|
require 'redmine_rate/hooks/plugin_timesheet_views_timesheet_group_header_hook'
|
||||||
require 'redmine_rate/hooks/plugin_timesheet_views_timesheet_time_entry_hook'
|
require 'redmine_rate/hooks/plugin_timesheet_views_timesheet_time_entry_hook'
|
||||||
require 'redmine_rate/hooks/plugin_timesheet_views_timesheet_time_entry_sum_hook'
|
require 'redmine_rate/hooks/plugin_timesheet_views_timesheet_time_entry_sum_hook'
|
||||||
|
require 'redmine_rate/hooks/plugin_timesheet_view_timesheets_report_header_tags_hook'
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
module RedmineRate
|
||||||
|
module Hooks
|
||||||
|
class PluginTimesheetViewTimesheetsReportHeaderTagsHook < Redmine::Hook::ViewListener
|
||||||
|
def plugin_timesheet_view_timesheets_report_header_tags(context={})
|
||||||
|
return content_tag(:style,
|
||||||
|
'tr.missing-rate td.cost { color: red; }',
|
||||||
|
:type => 'text/css')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -2,7 +2,7 @@ module RedmineRate
|
|||||||
module Hooks
|
module Hooks
|
||||||
class PluginTimesheetViewsTimesheetGroupHeaderHook < Redmine::Hook::ViewListener
|
class PluginTimesheetViewsTimesheetGroupHeaderHook < Redmine::Hook::ViewListener
|
||||||
def plugin_timesheet_views_timesheet_group_header(context={})
|
def plugin_timesheet_views_timesheet_group_header(context={})
|
||||||
return ''
|
return content_tag(:th, l(:rate_cost), :width => '8%')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,9 +1,18 @@
|
|||||||
module RedmineRate
|
module RedmineRate
|
||||||
module Hooks
|
module Hooks
|
||||||
class PluginTimesheetViewsTimesheetTimeEntryHook < Redmine::Hook::ViewListener
|
class PluginTimesheetViewsTimesheetTimeEntryHook < Redmine::Hook::ViewListener
|
||||||
|
include TimesheetHookHelper
|
||||||
|
|
||||||
def plugin_timesheet_views_timesheet_time_entry(context={})
|
def plugin_timesheet_views_timesheet_time_entry(context={})
|
||||||
return ''
|
cost = cost_item(context[:time_entry])
|
||||||
|
if cost
|
||||||
|
td_cell(number_to_currency(cost))
|
||||||
|
else
|
||||||
|
td_cell(' ')
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,8 +1,16 @@
|
|||||||
module RedmineRate
|
module RedmineRate
|
||||||
module Hooks
|
module Hooks
|
||||||
class PluginTimesheetViewsTimesheetTimeEntrySumHook < Redmine::Hook::ViewListener
|
class PluginTimesheetViewsTimesheetTimeEntrySumHook < Redmine::Hook::ViewListener
|
||||||
|
include TimesheetHookHelper
|
||||||
|
|
||||||
def plugin_timesheet_views_timesheet_time_entry_sum(context={})
|
def plugin_timesheet_views_timesheet_time_entry_sum(context={})
|
||||||
return ''
|
time_entries = context[:time_entries]
|
||||||
|
costs = time_entries.collect {|time_entry| cost_item(time_entry)}.compact.sum
|
||||||
|
if costs >= 0
|
||||||
|
return td_cell(number_to_currency(costs))
|
||||||
|
else
|
||||||
|
return td_cell(' ')
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,8 +1,20 @@
|
|||||||
module RedmineRate
|
module RedmineRate
|
||||||
module Hooks
|
module Hooks
|
||||||
class PluginTimesheetViewsTimesheetsTimeEntryRowClassHook < Redmine::Hook::ViewListener
|
class PluginTimesheetViewsTimesheetsTimeEntryRowClassHook < Redmine::Hook::ViewListener
|
||||||
|
include TimesheetHookHelper
|
||||||
|
|
||||||
def plugin_timesheet_views_timesheets_time_entry_row_class(context={})
|
def plugin_timesheet_views_timesheets_time_entry_row_class(context={})
|
||||||
return ''
|
time_entry = context[:time_entry]
|
||||||
|
return "" unless time_entry
|
||||||
|
|
||||||
|
cost = cost_item(time_entry)
|
||||||
|
return "" unless cost # Permissions
|
||||||
|
|
||||||
|
if cost && cost <= 0
|
||||||
|
return "missing-rate"
|
||||||
|
else
|
||||||
|
return ""
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
14
lib/redmine_rate/hooks/timesheet_hook_helper.rb
Normal file
14
lib/redmine_rate/hooks/timesheet_hook_helper.rb
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
module TimesheetHookHelper
|
||||||
|
# Returns the cost of a time entry, checking user permissions
|
||||||
|
def cost_item(time_entry)
|
||||||
|
if User.current.logged? && (User.current.allowed_to?(:view_rate, time_entry.project) || User.current.admin?)
|
||||||
|
return time_entry.cost
|
||||||
|
else
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def td_cell(html)
|
||||||
|
return content_tag(:td, html, :align => 'right', :class => 'cost')
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
require File.dirname(__FILE__) + '/../../../../test_helper'
|
||||||
|
|
||||||
|
class RedmineRate::Hooks::PluginTimesheetViewTimesheetsReportHeaderTagsTest < ActionController::TestCase
|
||||||
|
include Redmine::Hook::Helper
|
||||||
|
|
||||||
|
def controller
|
||||||
|
@controller ||= ApplicationController.new
|
||||||
|
@controller.response ||= ActionController::TestResponse.new
|
||||||
|
@controller
|
||||||
|
end
|
||||||
|
|
||||||
|
def request
|
||||||
|
@request ||= ActionController::TestRequest.new
|
||||||
|
end
|
||||||
|
|
||||||
|
def hook(args={})
|
||||||
|
call_hook :plugin_timesheet_view_timesheets_report_header_tags, args
|
||||||
|
end
|
||||||
|
|
||||||
|
context "#plugin_timesheet_view_timesheets_report_header_tags" do
|
||||||
|
should "return a css string" do
|
||||||
|
@response.body = hook
|
||||||
|
assert_select "style", :text => /missing-rate/
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -18,9 +18,9 @@ class RedmineRate::Hooks::PluginTimesheetViewsTimesheetGroupHeaderTest < ActionC
|
|||||||
end
|
end
|
||||||
|
|
||||||
context "#plugin_timesheet_views_timesheet_group_header" do
|
context "#plugin_timesheet_views_timesheet_group_header" do
|
||||||
should "return an empty string" do
|
should "render the cost table header" do
|
||||||
@response.body = hook
|
@response.body = hook
|
||||||
assert @response.body.blank?
|
assert_select "th", :text => "Cost"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -18,9 +18,30 @@ class RedmineRate::Hooks::PluginTimesheetViewsTimesheetTimeEntryTest < ActionCon
|
|||||||
end
|
end
|
||||||
|
|
||||||
context "#plugin_timesheet_views_timesheet_time_entry" do
|
context "#plugin_timesheet_views_timesheet_time_entry" do
|
||||||
should "return an empty string" do
|
context "for users with view rate permission" do
|
||||||
@response.body = hook
|
should "render a cost cell showing the cost for the time entry" do
|
||||||
assert @response.body.blank?
|
User.current = User.generate!(:admin => true)
|
||||||
|
rate = Rate.generate!(:amount => 100)
|
||||||
|
time_entry = TimeEntry.generate!(:hours => 2, :rate => rate)
|
||||||
|
|
||||||
|
@response.body = hook(:time_entry => time_entry)
|
||||||
|
|
||||||
|
assert_select 'td', :text => "$200.00"
|
||||||
|
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context "for users without view rate permission" do
|
||||||
|
should "render an empty cost cell" do
|
||||||
|
User.current = nil
|
||||||
|
rate = Rate.generate!(:amount => 100)
|
||||||
|
time_entry = TimeEntry.generate!(:hours => 2, :rate => rate)
|
||||||
|
|
||||||
|
@response.body = hook(:time_entry => time_entry)
|
||||||
|
|
||||||
|
assert_select 'td', :text => ' '
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -18,9 +18,31 @@ class RedmineRate::Hooks::PluginTimesheetViewsTimesheetTimeEntrySumTest < Action
|
|||||||
end
|
end
|
||||||
|
|
||||||
context "#plugin_timesheet_views_timesheet_time_entry_sum" do
|
context "#plugin_timesheet_views_timesheet_time_entry_sum" do
|
||||||
should "return an empty string" do
|
context "for users with view rate permission" do
|
||||||
@response.body = hook
|
should "render a cost cell showing the total cost for the time entries" do
|
||||||
assert @response.body.blank?
|
User.current = User.generate!(:admin => true)
|
||||||
|
rate = Rate.generate!(:amount => 100)
|
||||||
|
time_entry1 = TimeEntry.generate!(:hours => 2, :rate => rate)
|
||||||
|
time_entry2 = TimeEntry.generate!(:hours => 10, :rate => rate)
|
||||||
|
|
||||||
|
@response.body = hook(:time_entries => [time_entry1, time_entry2])
|
||||||
|
|
||||||
|
assert_select 'td', :text => "$1,200.00"
|
||||||
|
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context "for users without view rate permission" do
|
||||||
|
should "render an empty cost cell" do
|
||||||
|
User.current = nil
|
||||||
|
rate = Rate.generate!(:amount => 100)
|
||||||
|
time_entry = TimeEntry.generate!(:hours => 2, :rate => rate)
|
||||||
|
|
||||||
|
@response.body = hook(:time_entries => [time_entry])
|
||||||
|
|
||||||
|
assert_select 'td', :text => '$0.00'
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -18,9 +18,43 @@ class RedmineRate::Hooks::PluginTimesheetViewsTimesheetsTimeEntryRowClassTest <
|
|||||||
end
|
end
|
||||||
|
|
||||||
context "#plugin_timesheet_views_timesheets_time_entry_row_class" do
|
context "#plugin_timesheet_views_timesheets_time_entry_row_class" do
|
||||||
should "return an empty string" do
|
context "for users with view rate permission" do
|
||||||
@response.body = hook
|
setup do
|
||||||
assert @response.body.blank?
|
User.current = User.generate!(:admin => true)
|
||||||
|
end
|
||||||
|
|
||||||
|
should "render a missing rate css class if the time entry has no cost" do
|
||||||
|
time_entry = TimeEntry.generate!(:hours => 2, :rate => nil)
|
||||||
|
|
||||||
|
assert_equal "missing-rate", hook(:time_entry => time_entry)
|
||||||
|
end
|
||||||
|
|
||||||
|
should "render nothing if the time entry has a cost" do
|
||||||
|
rate = Rate.generate!(:amount => 100)
|
||||||
|
time_entry = TimeEntry.generate!(:hours => 2, :rate => rate)
|
||||||
|
|
||||||
|
assert_equal "", hook(:time_entry => time_entry)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context "for users without view rate permission" do
|
||||||
|
setup do
|
||||||
|
User.current = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
should "render nothing if the time entry has no cost" do
|
||||||
|
time_entry = TimeEntry.generate!(:hours => 2, :rate => nil)
|
||||||
|
|
||||||
|
assert_equal "", hook(:time_entry => time_entry)
|
||||||
|
end
|
||||||
|
|
||||||
|
should "render nothing if the time entry has a cost" do
|
||||||
|
rate = Rate.generate!(:amount => 100)
|
||||||
|
time_entry = TimeEntry.generate!(:hours => 2, :rate => rate)
|
||||||
|
|
||||||
|
assert_equal "", hook(:time_entry => time_entry)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user