3scale/porta

View on GitHub
app/observers/billing_observer.rb

Summary

Maintainability
A
0 mins
Test Coverage
# frozen_string_literal: true
class BillingObserver < ActiveRecord::Observer

  class RangeForVariableCost < Range
    def distance_in_seconds
      (self.end.in_time_zone('UTC') - self.begin.in_time_zone('UTC')).to_i
    end

    def empty?
      distance_in_seconds.zero?
    end
  end

  observe :contract

  # It is called 'manually' from Contract#notify_plan_changed

  def bill_variable_for_plan_changed(contract, plan)
    if contract.provider_account.provider_can_use?(:instant_bill_plan_change)
      invoice_period = Month.new(Time.now)
      current_invoice = Finance::InvoiceProxy.new(contract.account, invoice_period)
      current_invoice.mark_as_used

      period_from = [contract.variable_cost_paid_until, invoice_period.begin].max
      last_midnight = Date.today.beginning_of_day
      period = RangeForVariableCost.new(period_from, last_midnight)

      contract.bill_for_variable(period, current_invoice, plan) unless period.try(:empty?)
    end
  end

  def plan_changed(contract)
    now = Time.now.utc

    strategy = contract.buyer_account.provider_account.try(:billing_strategy)

    entitlements_options = { previous_plan: contract.old_plan }

    if !contract.trial?(now) && strategy
      period = TimeRange.new(now, now.end_of_month)
      entitlements_options[:invoice] = strategy.bill_plan_change(contract, period).try(:invoice)
      contract.update_attribute :paid_until, now.end_of_month # TODO: move this line inside the billing strategy
    end

    SupportEntitlementsService.notify_entitlements(contract.account, entitlements_options)
  end
end