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
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
# File 'app/models/gold/billing.rb', line 112 def after_shop_update! return_url = Engine.routes.url_helpers.process_charge_url Gold.logger.info("Received shop update from '#{shop.shopify_domain}'") 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
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 |
# File 'app/models/gold/billing.rb', line 134 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
106 107 108 |
# File 'app/models/gold/billing.rb', line 106 def calculate_price(tier) tier.monthly_price * (100 - discount_percentage) / 100 end |
#calculate_trial_days(tier, now = Time.current) ⇒ Object
87 88 89 90 91 92 93 94 95 96 |
# File 'app/models/gold/billing.rb', line 87 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
72 73 74 |
# File 'app/models/gold/billing.rb', line 72 def last_selected_tier @last_selected_tier ||= find_last_selected_tier end |
#qualifies_for_tier?(tier) ⇒ Boolean
98 99 100 |
# File 'app/models/gold/billing.rb', line 98 def qualifies_for_tier?(tier) shop ? shop.qualifies_for_tier?(tier) : true end |
#shopify_plan ⇒ Object
Returns the Shopify plan for this shop.
77 78 79 80 81 82 83 84 85 |
# File 'app/models/gold/billing.rb', line 77 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
63 64 65 |
# File 'app/models/gold/billing.rb', line 63 def tier @tier ||= Tier.find(tier_id) end |
#tier=(tier) ⇒ Object
67 68 69 70 |
# File 'app/models/gold/billing.rb', line 67 def tier=(tier) @tier = tier self[:tier_id] = tier.id end |
#trial_days_left ⇒ Object
102 103 104 |
# File 'app/models/gold/billing.rb', line 102 def trial_days_left calculate_trial_days(tier) end |