Class: Gold::Billing
- Inherits:
-
ApplicationRecord
- Object
- ApplicationRecord
- Gold::Billing
- 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
- .initial_state ⇒ Object
-
.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.
- .transition_class ⇒ Object
Instance Method Summary collapse
-
#after_shop_update! ⇒ Object
Provides a way to let Gold know that the shop has changed.
-
#app_access? ⇒ Boolean
Shops within these states should not get access to the app or services.
- #calculate_price(tier) ⇒ Object
- #calculate_trial_days(tier, now = Time.current) ⇒ Object
- #last_selected_tier ⇒ Object
- #qualifies_for_tier?(tier) ⇒ Boolean
-
#shopify_plan ⇒ Object
Returns the Shopify plan for this shop.
-
#state_machine ⇒ Object
rubocop:enable Rails/ReflectionClassName.
- #tier ⇒ Object
- #tier=(tier) ⇒ Object
- #trial_days_left ⇒ Object
Class Method Details
.initial_state ⇒ Object
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_class ⇒ Object
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
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 |
# File 'app/models/gold/billing.rb', line 110 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. # 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 |
#app_access? ⇒ Boolean
Shops within these states should not get access to the app or services
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 |
# File 'app/models/gold/billing.rb', line 132 def app_access? blacklist = %i[ new accepted_terms select_tier sudden_charge sudden_charge_declined sudden_charge_expired marked_as_suspended suspended frozen delinquent marked_as_uninstalled uninstalled cleanup done ] !blacklist.include?(current_state) end |
#calculate_price(tier) ⇒ Object
104 105 106 |
# File 'app/models/gold/billing.rb', line 104 def calculate_price(tier) tier.monthly_price * (100 - discount_percentage) / 100 end |
#calculate_trial_days(tier, now = Time.current) ⇒ Object
85 86 87 88 89 90 91 92 93 94 |
# File 'app/models/gold/billing.rb', line 85 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_tier ⇒ Object
70 71 72 |
# File 'app/models/gold/billing.rb', line 70 def last_selected_tier @last_selected_tier ||= find_last_selected_tier end |
#qualifies_for_tier?(tier) ⇒ Boolean
96 97 98 |
# File 'app/models/gold/billing.rb', line 96 def qualifies_for_tier?(tier) shop ? shop.qualifies_for_tier?(tier) : true end |
#shopify_plan ⇒ Object
Returns the Shopify plan for this shop.
75 76 77 78 79 80 81 82 83 |
# File 'app/models/gold/billing.rb', line 75 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_machine ⇒ Object
rubocop:enable Rails/ReflectionClassName
47 48 49 50 51 |
# File 'app/models/gold/billing.rb', line 47 def state_machine transition_class = self.class.transition_class @state_machine ||= Machine.new(self, transition_class: transition_class, association_name: :transitions) end |
#tier ⇒ Object
61 62 63 |
# File 'app/models/gold/billing.rb', line 61 def tier @tier ||= Tier.find(tier_id) end |
#tier=(tier) ⇒ Object
65 66 67 68 |
# File 'app/models/gold/billing.rb', line 65 def tier=(tier) @tier = tier self[:tier_id] = tier.id end |
#trial_days_left ⇒ Object
100 101 102 |
# File 'app/models/gold/billing.rb', line 100 def trial_days_left calculate_trial_days(tier) end |