A cost value wasn't getting recaclulated by TimeEntry#cost when the attributes were changing. It only was recalculated when .cost changed.
80 lines
1.9 KiB
Ruby
80 lines
1.9 KiB
Ruby
module RateTimeEntryPatch
|
|
def self.included(base) # :nodoc:
|
|
base.extend(ClassMethods)
|
|
|
|
base.send(:include, InstanceMethods)
|
|
|
|
# Same as typing in the class
|
|
base.class_eval do
|
|
unloadable # Send unloadable so it will not be unloaded in development
|
|
belongs_to :rate
|
|
|
|
before_save :recalculate_cost
|
|
|
|
end
|
|
|
|
end
|
|
|
|
module ClassMethods
|
|
# Updated the cached cost of all TimeEntries for user and project
|
|
def update_cost_cache(user, project=nil)
|
|
c = ARCondition.new
|
|
c << ["#{TimeEntry.table_name}.user_id = ?", user]
|
|
c << ["#{TimeEntry.table_name}.project_id = ?", project] if project
|
|
|
|
TimeEntry.all(:conditions => c.conditions).each do |time_entry|
|
|
time_entry.save_cached_cost
|
|
end
|
|
end
|
|
end
|
|
|
|
module InstanceMethods
|
|
# Returns the current cost of the TimeEntry based on it's rate and hours
|
|
#
|
|
# Is a read-through cache method
|
|
def cost(options={})
|
|
store_to_db = options[:store] || false
|
|
|
|
unless read_attribute(:cost)
|
|
if self.rate.nil?
|
|
amount = Rate.amount_for(self.user, self.project, self.spent_on.to_s)
|
|
else
|
|
amount = rate.amount
|
|
end
|
|
|
|
if amount.nil?
|
|
write_attribute(:cost, 0.0)
|
|
else
|
|
if store_to_db
|
|
# Write the cost to the database for caching
|
|
update_attribute(:cost, amount.to_f * hours.to_f)
|
|
else
|
|
# Cache to object only
|
|
write_attribute(:cost, amount.to_f * hours.to_f)
|
|
end
|
|
end
|
|
end
|
|
|
|
read_attribute(:cost)
|
|
end
|
|
|
|
def clear_cost_cache
|
|
write_attribute(:cost, nil)
|
|
end
|
|
|
|
def save_cached_cost
|
|
clear_cost_cache
|
|
update_attribute(:cost, cost)
|
|
end
|
|
|
|
def recalculate_cost
|
|
clear_cost_cache
|
|
cost(:store => false)
|
|
true # for callback
|
|
end
|
|
|
|
end
|
|
end
|
|
|
|
|