app/models/group_cost.rb
class GroupCost
attr_reader :group, :start_date, :end_date
def initialize(group, start_date, end_date)
@group, @start_date, @end_date = [ group, start_date, end_date ]
end
# returns
# { person => {
# some_plane => { count: 1, cost: 233 },
# some_wire_launcher => { count: 2, cost 100 }
# },...
# }
def people_with_sorted_cost
unless @people_with_sorted_cost
res = group.people.map do |person|
[ person, sorted_cost_for(person) ]
end
@people_with_sorted_cost = Hash[res]
end
@people_with_sorted_cost
end
def cost_by_rule
@cost_by_rule ||= flights.map do |flight|
[flight, flight.launch]
end.flatten.compact.map do |item|
{item: item, cost: item.try(:cost)}
end.select do |item|
!item[:cost].empty?
end.group_by do |item|
item[:cost].cost_rule
end.map do |cost_rule, costs|
[cost_rule, costs.map do |cost|
cost_for_item(cost[:item], 1)
end.compact.reduce do |a, b|
{ cost: a[:cost] + b[:cost], count: a[:count] + b[:count] }
end]
end
end
def sum_for_person(person)
liabilities_for(person).map(&:value).sum
end
def sum
liabilities.map(&:value).sum
end
def settle(text, account)
accounting_session = AccountingSession.create(name: text, voucher_number: 0, accounting_date: Date.today, without_flights: true)
group.people.each do |person|
accounting_session.manual_accounting_entries.create(from: account, to: person.financial_account, text: text, value: sum_for_person(person))
end
accounting_session
end
private
def sorted_cost_for(person)
foo = liabilities_for(person).map do |liability|
cost_for(liability)
end
foo = foo.select { |h| !h.keys.empty? }
x = foo.map(&:keys).flatten.uniq
r = {}
x.each do |k|
r[k] = foo.map { |h| h[k] }.compact.reduce do |a, b|
{ cost: a[:cost] + b[:cost], count: a[:count] + b[:count] }
end
end
r
end
def flights
@flights ||= group.flights.where('departure_date BETWEEN ? AND ?', start_date, end_date).select { |flight| flight.is_a?(Flight) }
end
def liabilities
@liabilities ||= flights.map(&:liabilities_with_default).flatten
end
def liabilities_for(person)
liabilities.select do |liability|
liability.person.id == person.id
end
end
def cost_for(liability)
cost = {}
flight = liability.flight
proportion = flight.proportion_for(liability)
if flight.cost.free_sum > 0
cost[flight.plane] = cost_for_item(flight, proportion)
end
if flight.launch.is_a?(WireLaunch)
cost[flight.launch.wire_launcher] = cost_for_item(flight.launch, proportion)
elsif flight.launch.is_a?(TowFlight)
cost[flight.launch.plane] = cost_for_item(flight.launch, proportion)
end
cost
end
def cost_for_item(item, proportion)
if item.is_a?(AbstractFlight)
count = item.duration
elsif item.is_a?(WireLaunch)
count = 1
end
{ count: count, cost: (item.cost.free_sum.to_f * proportion).round }
end
end