Skip to content

Instantly share code, notes, and snippets.

@eLafo
Created February 25, 2014 16:10
Show Gist options
  • Save eLafo/9211985 to your computer and use it in GitHub Desktop.
Save eLafo/9211985 to your computer and use it in GitHub Desktop.
class MainGraph
include ActiveModel::Validations
attr_reader :company, :starts_at, :ends_at
#attr_reader :graph_window_at, :period_search, :project_periods, :onthebench, :billable_by_period, :unbillable_by_period,
# :free_by_period, :billable, :unbillable, :free, :graph_form
validate :validate_graph
#def initialize(weeks_number, graph_form, company)
# @weeks_number = weeks_number
# @graph_form = graph_form
# @company = company
#end
def initialize(company, starts_at = Date.today.at_beginning_of_week, ends_at = Date.today.at_end_of_week)
@company = company
@starts_at = starts_at
@ends_at = ends_at
end
def participates_by_resource
company.projects.inject([]) do |res, project|
res << [project, build_participates_info(project.participates)]
end
end
def build_participates_info(participates)
dates_from_participates(participates).inject([]) do |res, pair_of_dates|
res << [pair_of_dates, participates.select{|p| p.begin_date <= pair_of_dates.first && p.end_date >= pair_of_dates.last}]
end
end
def dates_from_participates(participates)
h = participates.inject({starts_at: [], ends_at: []}) do |res, participate|
res[:starts_at] << [participate.begin_date, starts_at].max if participate.begin_date <= ends_at
res[:ends_at] << [participate.end_date, ends_at].min if participate.end_date >= starts_at
res
end
h[:starts_at].uniq!
h[:ends_at].uniq!
(h[:starts_at] + h[:ends_at]).sort.each_cons(2)
#.uniq.sort.each_cons(2)
end
def show_main_line_graph
if @graph_form
@graph_window_at = Date.strptime(@graph_form[:central_date], '%Y-%m-%d')
if @graph_form[:action] == 'prev'
@graph_window_at = @graph_window_at - 1.weeks
else
@graph_window_at = @graph_window_at + 1.weeks
end
else
@graph_window_at = Date.today.beginning_of_week
end
graph_window_to = @graph_window_at + @weeks_number.weeks
@period_search = "From #{@graph_window_at.strftime('%d/%m/%Y')} to #{graph_window_to.strftime('%d/%m/%Y')}"
@project_periods= []
periods = []
rangeold = nil
#return resources participating in a project in a specified time
participates = @company.participates.joins(project: :client).
order('projects.billable desc, clients.name, projects.name').
containing_date(@graph_window_at, graph_window_to)
# select distinct projects
projects = participates.group(:project_id)
projects.each do |project|
# selects participates of that project id and sets graph_window_at if begin_date is older, sets graph_window_to if begin_date is newer
participates_by_project = participates.with_project_id(project.project_id).each do |participate|
participate.end_date = participate.end_date + 1.days
participate.begin_date = @graph_window_at if participate.begin_date < @graph_window_at
participate.end_date = graph_window_to if participate.end_date > graph_window_to
end
#splits every date and search between this dates how many resources the company has
participate_days = participates_by_project.map { |x| [x.begin_date, x.end_date] }.flatten.uniq.sort
participate_days.each do |range|
if rangeold
participate = @company.participates.with_project_id(project.project_id).
where('participates.begin_date <= DATE(?) and DATE(?) <= participates.end_date', rangeold, rangeold)
periods.push(Period.new(participate, rangeold, range)) unless participate.blank?
end
rangeold=range
end
@project_periods.push(ProjectPeriod.new(project, periods))
periods = []
rangeold = nil
end
end
# show bar charts under the lines chart
def show_percentajes_bar_chart
@billable = []
@unbillable = []
@free = []
@onthebench = []
@weeks_number.times do |weeknumber|
begin_date = @graph_window_at + weeknumber.weeks
end_date = begin_date + 1.week
participates_by_project = @company.participates.containing_date(begin_date, end_date).each do |participate|
participate.end_date = participate.end_date + 1.days
participate.begin_date = begin_date if participate.begin_date < begin_date
participate.end_date = end_date if participate.end_date > end_date
end
participate_days = participates_by_project.map { |x| [x.begin_date, x.end_date] }.flatten.uniq.sort
arr = []
dateold = nil
participate_days.each do |date_index|
if dateold
workingpeople = @company.participates.
where('participates.begin_date <= DATE(?) and DATE(?) <= participates.end_date', dateold, dateold)
working = workingpeople.inject(0) { |sum, e| sum.to_f + e.dedication_percent.to_f } / 100.0
notworking = @company.resources.active(dateold, date_index).where.not(id: workingpeople.pluck(:resource_id).uniq)
@onthebench.push(Period.new(notworking, dateold, date_index))
total_resources = @company.resources.active(dateold, date_index).count
billable = @company.participates.
where('participates.billable=1 and participates.begin_date <= DATE(?) and DATE(?) <= participates.end_date', dateold, dateold).
joins(:project).where(projects: {billable: 1}).
inject(0) { |sum, e| sum.to_f + e.dedication_percent.to_f } / 100.0
arr.push(Utilization.new(dateold, date_index, total_resources, billable, working))
end
dateold = date_index
end
@billable.push(arr.count > 0 ? arr.inject(0) { |sum, e| sum += e.billable }/arr.count : 0)
@unbillable.push(arr.count > 0 ? arr.inject(0) { |sum, e| sum += e.unbillable }/arr.count : 0)
@free.push(arr.count > 0 ? arr.inject(0) { |sum, e| sum += e.free }/arr.count : 0)
end
end
def show_semicircle_chart
# for the semicircle chart
total_sum_billable = @billable.inject(0) { |sum, e| sum += e }
total_sum_unbillable = @unbillable.inject(0) { |sum, e| sum += e }
total_sum_free = @free.inject(0) { |sum, e| sum += e }
@billable_by_period = 0.0
@unbillable_by_period = 0.0
@free_by_period = 0.0
@billable_by_period = total_sum_billable/@billable.count if total_sum_billable > 0.0
@unbillable_by_period = total_sum_unbillable/@unbillable.count if total_sum_unbillable>0.0
@free_by_period = total_sum_free/@free.count if total_sum_free>0.0
end
def validate_graph
if @company.resources.blank?
errors.add(:resources, 'You need at least one resource, you can create one')
end
if @company.clients.blank?
errors.add(:clients, 'You need at least one client, you can create one')
end
if @company.projects.blank? && @company.clients.present?
errors.add(:projects, 'You need at least one project, you can create one')
end
if @company.projects.present? && @company.resources.present? && @company.participates.blank?
errors.add(:participates, 'You need at least one participate, you can create one')
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment