Class: Gold::Billing

Inherits:
ApplicationRecord
  • Object
show all
Includes:
Statesman::Adapters::ActiveRecordQueries
Defined in:
app/models/gold/billing.rb

Overview

Class that tracks all billing details. Intended to be associated with a shop class that the app uses

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.initial_stateObject



14
15
16
# File 'app/models/gold/billing.rb', line 14

def initial_state
  :new
end

.lookup_for_domain!(domain) ⇒ Object

Finds a billing instance for a particular shop, using the shop’s domain as the key to look it up. Because this is not stored in the Billing model, a join against the shop association is required.



21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'app/models/gold/billing.rb', line 21

def lookup_for_domain!(domain)
  # This is a little bit hard to follow, but `#joins` uses the name of the
  # association as defined below as "shop" and `#where` expects the name
  # of the associated table, which we can query from the class using
  # `#table_name`.
  joins(:shop)
    .where(
      Gold.shop_class.table_name => {
        Gold.shop_domain_attribute => domain
      }
    )
    .first!
end

.transition_classObject



10
11
12
# File 'app/models/gold/billing.rb', line 10

def transition_class
  Gold::Transition
end

Instance Method Details

#after_shop_update!Object

Provides a way to let Gold know that the shop has changed. Your app should call this whenever a new shop update webhook is received or is manually overridden



106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'app/models/gold/billing.rb', line 106

def after_shop_update!
  return_url = Engine.routes.url_helpers.process_charge_url

  Gold.logger.info("Received shop update from '#{shop.shopify_domain}'")

  shop.with_shopify_session do
    case current_state
    when :affiliate
      if shopify_plan.paying?
        # If an affiliate has converted, change them to a paid plan
        ConvertAffiliateToPaidOp.new(self, return_url).call
      end
    when :billing
      # If their plan has been frozen, move to frozen state
      FreezeOp.new(self).call if can_transition_to?(:frozen)
    when :frozen
      CheckChargeOp.new(self).call unless shopify_plan.frozen?
    end
  end
end

#calculate_price(tier) ⇒ Object



100
101
102
# File 'app/models/gold/billing.rb', line 100

def calculate_price(tier)
  tier.monthly_price * (100 - discount_percentage) / 100
end

#calculate_trial_days(tier, now = Time.current) ⇒ Object



81
82
83
84
85
86
87
88
89
90
# File 'app/models/gold/billing.rb', line 81

def calculate_trial_days(tier, now = Time.current)
  starts_at = trial_starts_at || now
  trial_ends_at = starts_at.advance(days: tier.trial_days)
  trial_period = trial_ends_at - now
  if trial_period > 0
    (trial_period / 1.day).ceil
  else
    0
  end
end

#last_selected_tierObject



66
67
68
# File 'app/models/gold/billing.rb', line 66

def last_selected_tier
  @last_selected_tier ||= find_last_selected_tier
end

#qualifies_for_tier?(tier) ⇒ Boolean

Returns:

  • (Boolean)


92
93
94
# File 'app/models/gold/billing.rb', line 92

def qualifies_for_tier?(tier)
  shop ? shop.qualifies_for_tier?(tier) : true
end

#shopify_planObject

Returns the Shopify plan for this shop.



71
72
73
74
75
76
77
78
79
# File 'app/models/gold/billing.rb', line 71

def shopify_plan
  if shopify_plan_override
    ShopifyPlan.new(shopify_plan_override)
  elsif shop
    ShopifyPlan.new(shop.shopify_plan_name)
  else
    ShopifyPlan.new(ShopifyAPI::Shop.current.plan_name)
  end
end

#state_machineObject

rubocop:enable Rails/ReflectionClassName



43
44
45
46
47
# File 'app/models/gold/billing.rb', line 43

def state_machine
  transition_class = self.class.transition_class
  @state_machine ||= Machine.new(self, transition_class: transition_class,
                                       association_name: :transitions)
end

#tierObject



57
58
59
# File 'app/models/gold/billing.rb', line 57

def tier
  @tier ||= Tier.find(tier_id)
end

#tier=(tier) ⇒ Object



61
62
63
64
# File 'app/models/gold/billing.rb', line 61

def tier=(tier)
  @tier = tier
  self[:tier_id] = tier.id
end

#trial_days_leftObject



96
97
98
# File 'app/models/gold/billing.rb', line 96

def trial_days_left
  calculate_trial_days(tier)
end