Untitled

mail@pastecode.io avatar
unknown
plain_text
2 years ago
5.2 kB
2
Indexable
Never
# Representa a las reservas scheduled de la clase BookingSet y Suite::BookingsSet
# Agrupa toda su lógica para cálculos y otros.

class ScheduledBookingsSet
  attr_reader :bookings
  attr_reader :start_time, :end_time, :start_date, :end_date

  def initialize(bookings:, start_time: nil, end_time: nil)
    @bookings = bookings
    @ordered_bookings = booking.respond_to?(&:booking_closed_time) ? @bookings.sort_by(&:booking_closed_time) : @bookings.sort_by(&:datetime_start)

    @start_time = start_time || @ordered_bookings.first.try(:datetime_start)
    @end_time   = end_time || @ordered_bookings.last.try(:datetime_start)
    @start_date = @start_time ? @start_time.to_date : nil
    @end_date   = @end_time ? @end_time.to_date : nil
  end

  # Valor total de ventas
  def sales_value
    @bookings.respond_to?(:booking_price) ? @sales_value ||= @bookings.map(&:booking_price).sum : @sales_value ||= @bookings.map(&:final_price).sum
  end

  # Valor total de comisiones
  def commissions_value
    @bookings.respond_to?(:booking_commission) ? @commissions_value ||= @bookings.map(&:booking_commission).sum : @commissions_value ||= @bookings.map(&:final_commission).sum
  end

  # Impuesto asociado, según motel y país
  def tax_for_commissions(motel)
    @tax_for_commissions ||= begin
      if motel.invoiced_with_tax?
        (commissions_value * Rails.configuration.motelnow['tax_rate']).round
      else
        0
      end
    end
  end

  # Valor para usar en facturación
  def value_for_invoice(motel)
    commissions_value + tax_for_commissions(motel)
  end

  # Calcula estadísticas de ventas día por día
  def sales_data_by_day(motel)
    data = {
      start_date: @start_date.try(:strftime, '%Y-%m-%d'),
      end_date:   @end_date.try(:strftime, '%Y-%m-%d'),
      sales:      {}
    }

    unless @ordered_bookings.empty?
      (@start_date..@end_date).each do |date|
        date_format = date.strftime('%Y-%m-%d')
        data[:sales][date_format] = { sales_value: 0 }
      end

      @ordered_bookings.each do |booking|
        if booking.respond_to?(:booking_closed_time)
          date_format = booking.booking_closed_time.strftime('%Y-%m-%d')
          data[:sales][date_format][:sales_value] += booking.booking_price
        else
          date_format = booking.datetime_start.strftime('%Y-%m-%d')
          data[:sales][date_format][:sales_value] += booking.final_price
        end
      end
    end

    data
  end

  # Calcula estadísticas de ventas por habitación
  def sales_data_by_room(motel)
    data = {
      start_date: @start_date.try(:strftime, '%Y-%m-%d'),
      end_date:   @end_date.try(:strftime, '%Y-%m-%d'),
      sales:      {
        by_room: {},
        total: { value: 0, net_commission: 0, vat: 0, other_taxes: {}, total_commission: 0 }
      }
    }
    motel.other_taxes.each { |name, _| data[:sales][:total][:other_taxes][name] = 0 }

    # Tasa de impuesto según motel
    if motel.invoiced_with_tax?
      vat_rate = Rails.configuration.motelnow['tax_rate']
    else
      vat_rate = 0
    end

    # Calcula datos reserva por reserva
    unless @ordered_bookings.empty?
      @ordered_bookings.each do |booking|
        room_type_id = booking.respond_to?(:booking_room_type_id) ? booking.booking_room_type_id : booking.price.room.type_id

        unless current = data[:sales][:by_room][room_type_id]
          current = data[:sales][:by_room][room_type_id] = {
            name: booking.respond_to?(:booking_room_type_name) ? booking.booking_room_type_name : booking.price.room.room_type.name,
            value: 0,
            net_commission: 0,
            vat: 0,
            other_taxes: {},
            total_commission: 0
          }

          motel.other_taxes.each { |name, _| current[:other_taxes][name] = 0 }
        end

        if booking.respond_to?(:booking_price)
          current[:value] += booking.booking_price
          current[:net_commission] += booking.booking_commission
          current[:vat] += (booking.booking_commission * vat_rate).round

          motel.other_taxes.each { |name, rate| current[:other_taxes][name] += (booking.booking_commission * rate).round }
        else
          current[:value] += booking.final_price
          current[:net_commission] += booking.final_commission
          current[:vat] += (booking.final_commission * vat_rate).round
  
          motel.other_taxes.each { |name, rate| current[:other_taxes][name] += (booking.final_commission * rate).round }
        end
      end
    end

    # Calcula totales
    data[:sales][:by_room].each do |id, room|
      other_taxes = room[:other_taxes].sum { |_, value| value }
      room[:total_commission] = room[:net_commission] + room[:vat] + other_taxes

      data[:sales][:total][:value] += room[:value]
      data[:sales][:total][:net_commission] += room[:net_commission]
      data[:sales][:total][:vat] += room[:vat]
      data[:sales][:total][:total_commission] += room[:total_commission]
      motel.other_taxes.each { |name, _| data[:sales][:total][:other_taxes][name] += room[:other_taxes][name] }
    end

    data
  end
end