Added rdoc comments
This commit is contained in:
@@ -5,7 +5,8 @@ class DeliverablesController < ApplicationController
|
||||
|
||||
helper :sort
|
||||
include SortHelper
|
||||
|
||||
|
||||
# Main deliverable list
|
||||
def index
|
||||
sort_init "#{Deliverable.table_name}.id", "desc"
|
||||
sort_update
|
||||
@@ -31,11 +32,13 @@ class DeliverablesController < ApplicationController
|
||||
end
|
||||
end
|
||||
|
||||
# Action to preview the Deliverable description
|
||||
def preview
|
||||
@text = params[:deliverable][:description]
|
||||
render :partial => 'common/preview'
|
||||
end
|
||||
|
||||
# Saves a new Deliverable
|
||||
def create
|
||||
if params[:deliverable][:type] == FixedDeliverable.name
|
||||
@deliverable = FixedDeliverable.new(params[:deliverable])
|
||||
@@ -59,10 +62,12 @@ class DeliverablesController < ApplicationController
|
||||
|
||||
end
|
||||
|
||||
# Builds the edit form for the Deliverable
|
||||
def edit
|
||||
@deliverable = Deliverable.find_by_id_and_project_id(params[:deliverable_id], params[:id])
|
||||
end
|
||||
|
||||
# Updates an existing Deliverable, optionally changing it's type
|
||||
def update
|
||||
@deliverable = Deliverable.find(params[:deliverable_id])
|
||||
|
||||
@@ -82,6 +87,7 @@ class DeliverablesController < ApplicationController
|
||||
|
||||
end
|
||||
|
||||
# Removes the Deliverable
|
||||
def destroy
|
||||
@deliverable = Deliverable.find_by_id_and_project_id(params[:deliverable_id], @project.id)
|
||||
|
||||
@@ -102,6 +108,7 @@ class DeliverablesController < ApplicationController
|
||||
redirect_to :controller => 'issues', :action => 'index', :project_id => @project.id
|
||||
end
|
||||
|
||||
# Assigns issues to the Deliverable based on their Version
|
||||
def bulk_assign_issues
|
||||
@deliverable = Deliverable.find_by_id_and_project_id(params[:deliverable_id], @project.id)
|
||||
|
||||
|
||||
@@ -10,7 +10,8 @@ class Budget
|
||||
def initialize(project_id)
|
||||
@project = Project.find(project_id)
|
||||
end
|
||||
|
||||
|
||||
# Gets the next due date from the deliverables
|
||||
def next_due_date
|
||||
del = self.deliverables
|
||||
return nil unless del.size > 0
|
||||
@@ -20,6 +21,7 @@ class Budget
|
||||
return dates.sort[0]
|
||||
end
|
||||
|
||||
# Gets the last due date of the deliverables
|
||||
def final_due_date
|
||||
del = self.deliverables
|
||||
return nil unless del.size > 0
|
||||
@@ -29,14 +31,17 @@ class Budget
|
||||
return dates.sort[-1]
|
||||
end
|
||||
|
||||
# Deliverables assigned to this +Budget+
|
||||
def deliverables
|
||||
return Deliverable.find_all_by_project_id(@project.id)
|
||||
end
|
||||
|
||||
# Total budget all of the deliverables
|
||||
def budget
|
||||
return self.deliverables.collect(&:budget).inject { |sum, n| sum + n} || 0.0
|
||||
end
|
||||
|
||||
|
||||
# Amount of the budget spent. Expressed as as a percentage whole number
|
||||
def budget_ratio
|
||||
budget = self.budget # cache result
|
||||
if budget > 0.0
|
||||
@@ -46,14 +51,17 @@ class Budget
|
||||
end
|
||||
end
|
||||
|
||||
# Total amount spent for all the deliverables
|
||||
def spent
|
||||
self.deliverables.collect(&:spent).inject { |sum, n| sum + n } || 0.0
|
||||
end
|
||||
|
||||
# Amount of budget left on the deliverables
|
||||
def left
|
||||
return self.budget - self.spent
|
||||
end
|
||||
|
||||
# Amount spent over the budget
|
||||
def overruns
|
||||
if self.left >= 0
|
||||
return 0
|
||||
@@ -62,6 +70,7 @@ class Budget
|
||||
end
|
||||
end
|
||||
|
||||
# Completation progress, expressed as a percentage whole number
|
||||
def progress
|
||||
return 100 unless self.deliverables.size > 0
|
||||
return 100 if self.budget == 0.0
|
||||
@@ -75,10 +84,12 @@ class Budget
|
||||
return (balance / self.budget).round
|
||||
end
|
||||
|
||||
# Budget score. Will range from 100 (everything done with no money spent) to -100 (nothing done, all the money spent)
|
||||
def score
|
||||
return self.progress - self.budget_ratio
|
||||
end
|
||||
|
||||
# Total profit of the deliverables. This is *not* calculated based on the amount spent and total budget but is the total of the profit amount for the deliverables.
|
||||
def profit
|
||||
return 0.0 unless self.deliverables.size > 0
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
# A Deliverable is an item that is created as part of the project. These items
|
||||
# contain a collection of issues.
|
||||
class Deliverable < ActiveRecord::Base
|
||||
unloadable
|
||||
validates_presence_of :subject
|
||||
@@ -5,6 +7,7 @@ class Deliverable < ActiveRecord::Base
|
||||
belongs_to :project
|
||||
has_many :issues
|
||||
|
||||
# Assign all the issues with +version_id+ to this Deliverable
|
||||
def assign_issues_by_version(version_id)
|
||||
version = Version.find_by_id(version_id)
|
||||
return 0 if version.nil? || version.fixed_issues.blank?
|
||||
@@ -16,6 +19,10 @@ class Deliverable < ActiveRecord::Base
|
||||
return version.fixed_issues.size
|
||||
end
|
||||
|
||||
# Change the Deliverable type to another type. Valid types are
|
||||
#
|
||||
# * FixedDeliverable
|
||||
# * HourlyDeliverable
|
||||
def change_type(to)
|
||||
if [FixedDeliverable.name, HourlyDeliverable.name].include?(to)
|
||||
self.type = to
|
||||
@@ -26,16 +33,21 @@ class Deliverable < ActiveRecord::Base
|
||||
end
|
||||
end
|
||||
|
||||
# Adjusted score to show the status of the Deliverable. Will range from 100
|
||||
# (everything done with no money spent) to -100 (nothing done, all the money spent)
|
||||
def score
|
||||
return self.progress - self.budget_ratio
|
||||
end
|
||||
|
||||
# Amount spent. Virtual accessor that is overriden by subclasses.
|
||||
def spent
|
||||
0
|
||||
end
|
||||
|
||||
# TODO LATER: Shouldn't require the default_done_ratio patch
|
||||
# Percentage of the deliverable that is compelte based on the progress of the
|
||||
# assigned issues. Currently requires the +default_done_ratio+ patch.
|
||||
def progress
|
||||
# TODO LATER: Shouldn't require the default_done_ratio patch
|
||||
return 100 unless self.issues.size > 0
|
||||
|
||||
total ||= self.issues.collect(&:estimated_hours).delete_if {|e| e.nil? }.inject {|sum, n| sum + n} || 0
|
||||
@@ -50,14 +62,13 @@ class Deliverable < ActiveRecord::Base
|
||||
return (balance / total).round
|
||||
end
|
||||
|
||||
# Amount of the budget spent. Expressed as as a percentage whole number
|
||||
def budget_ratio
|
||||
return 0.0 if self.budget.nil? || self.budget == 0.0
|
||||
return ((self.spent / self.budget) * 100).round
|
||||
end
|
||||
|
||||
#
|
||||
# These attributes can take a Dollar amount or a %
|
||||
#
|
||||
# Setter for the overhead to take an Dollar amount or a %.
|
||||
def overhead=(v)
|
||||
if v.match(/%/)
|
||||
# Clear amount since this is a %
|
||||
@@ -71,6 +82,7 @@ class Deliverable < ActiveRecord::Base
|
||||
end
|
||||
end
|
||||
|
||||
# Setter for the materials to take an Dollar amount or a %.
|
||||
def materials=(v)
|
||||
if v.match(/%/)
|
||||
# Clear amount since this is a %
|
||||
@@ -84,6 +96,7 @@ class Deliverable < ActiveRecord::Base
|
||||
end
|
||||
end
|
||||
|
||||
# Setter for the profit to take an Dollar amount or a %.
|
||||
def profit=(v)
|
||||
if v.match(/%/)
|
||||
# Clear amount since this is a %
|
||||
@@ -97,22 +110,27 @@ class Deliverable < ActiveRecord::Base
|
||||
end
|
||||
end
|
||||
|
||||
# Amount of the budget remaining to be spent
|
||||
def budget_remaining
|
||||
return self.budget - self.spent
|
||||
end
|
||||
|
||||
# Number of hours used. Virtual accessor that is overriden by subclasses.
|
||||
def hours_used
|
||||
0
|
||||
end
|
||||
|
||||
# Amount spent on members. Virtual accessor that is overriden by subclasses.
|
||||
def members_spent
|
||||
[]
|
||||
end
|
||||
|
||||
# Amount of the budget remaining
|
||||
def left
|
||||
return self.budget - self.spent
|
||||
end
|
||||
|
||||
# Amount spent over the total budget
|
||||
def overruns
|
||||
if self.left >= 0
|
||||
return 0
|
||||
@@ -121,10 +139,12 @@ class Deliverable < ActiveRecord::Base
|
||||
end
|
||||
end
|
||||
|
||||
# Budget of labor, without counting profit or overheads. Virtual accessor that is overriden by subclasses.
|
||||
def labor_budget
|
||||
0
|
||||
end
|
||||
|
||||
# Helper method to return an Hash of the trackers and number of issues assigned to each tracker.
|
||||
def issues_with_trackers
|
||||
trackers = self.project.trackers
|
||||
return { } if trackers.empty?
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
class FixedDeliverable < Deliverable
|
||||
unloadable
|
||||
|
||||
# Fixed rate bids should always have a budget score of 0. This is because the budget is managed by the contractor.
|
||||
# FixedDeliverables should always have a budget score of 0. This is because the budget is managed by the contractor.
|
||||
def score
|
||||
0
|
||||
end
|
||||
|
||||
|
||||
# Returns the amount spent. It will always be related to the progress of the
|
||||
# FixedDeliverable because it is managed by the user
|
||||
def spent
|
||||
(self.progress.to_f / 100 ) * self.budget
|
||||
end
|
||||
|
||||
def profit
|
||||
def profit # :nodoc:
|
||||
if read_attribute(:profit_percent).nil?
|
||||
return super
|
||||
else
|
||||
@@ -18,6 +20,7 @@ class FixedDeliverable < Deliverable
|
||||
end
|
||||
end
|
||||
|
||||
# Budget for the labor, excluding overhead, profit, and materials
|
||||
def labor_budget
|
||||
return read_attribute(:fixed_cost)
|
||||
end
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
class HourlyDeliverable < Deliverable
|
||||
unloadable
|
||||
|
||||
# Amount of money spent on the issues. Determined by the Member's rate and
|
||||
# timelogs.
|
||||
def spent
|
||||
return 0 unless self.issues.size > 0
|
||||
total = 0.0
|
||||
@@ -17,17 +19,19 @@ class HourlyDeliverable < Deliverable
|
||||
return total
|
||||
end
|
||||
|
||||
# Number of hours used by Members on the Deliverable's issues
|
||||
def hours_used
|
||||
return 0 unless self.issues.size > 0
|
||||
return self.issues.collect(&:time_entries).flatten.collect(&:hours).sum
|
||||
|
||||
end
|
||||
|
||||
# Amount of time and money spent by the Members on the Deliverable's issues.
|
||||
def members_spent
|
||||
return MemberSpent.find_all_by_deliverable(self)
|
||||
end
|
||||
|
||||
def profit
|
||||
def profit # :nodoc:
|
||||
if read_attribute(:profit_percent).nil?
|
||||
return super
|
||||
else
|
||||
@@ -35,6 +39,7 @@ class HourlyDeliverable < Deliverable
|
||||
end
|
||||
end
|
||||
|
||||
# Budget for the labor, excluding overhead, profit, and materials
|
||||
def labor_budget
|
||||
return read_attribute(:cost_per_hour).to_f * read_attribute(:total_hours).to_f
|
||||
end
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
# Plain Ruby class to help build a data structure that lists
|
||||
# each member and the amount of time and money they spent.
|
||||
class MemberSpent
|
||||
attr_accessor :user
|
||||
attr_accessor :hours
|
||||
attr_accessor :spent
|
||||
|
||||
# New data structure to hold the Member's data
|
||||
def initialize(options = { })
|
||||
self.user = options[:user] || nil
|
||||
self.hours = options[:hours] || 0.0
|
||||
self.spent = options[:spent] || 0.0
|
||||
end
|
||||
|
||||
# Get all the Members, their hours used, and their money spent
|
||||
def self.find_all_by_deliverable(deliverable)
|
||||
membership = []
|
||||
return membership unless deliverable.issues.size > 0
|
||||
|
||||
Reference in New Issue
Block a user