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