app/models/tang/subscription.rb in tang-0.0.1 vs app/models/tang/subscription.rb in tang-0.0.8
- old
+ new
@@ -1,20 +1,146 @@
module Tang
class Subscription < ActiveRecord::Base
+ include AASM
has_paper_trail
- belongs_to :customer, class_name: Tang.customer_class
+ aasm column: 'status' do
+ state :trialing, initial: true
+ state :active
+ state :past_due
+ state :canceled
+ state :unpaid
+
+ event :activate do
+ transitions from: :trialing, to: :active
+ end
+
+ event :fail do
+ transitions from: [:trialing, :active], to: :past_due
+ end
+
+ event :cancel, after: :cancel_stripe_subscription do
+ transitions from: [:trialing, :active, :past_due], to: :canceled
+ end
+
+ event :close do
+ transitions from: :past_due, to: :unpaid
+ end
+ end
+
+ belongs_to :customer, class_name: Tang.customer_class.to_s
belongs_to :plan
+ belongs_to :coupon
+ has_many :invoices, dependent: :destroy
- validates :customer, uniqueness: true
- validates :stripe_id, uniqueness: true
+ validates :customer, presence: true
+ validates :plan, presence: true
+ validates :stripe_id, presence: true, uniqueness: true
validates :application_fee_percent, numericality: { greater_than_or_equal_to: 0 }, allow_nil: true
validates :quantity, numericality: { greater_than_or_equal_to: 0 }, allow_nil: true
- validates :tax_percent, numericality: { greater_than_or_equal_to: 0 }, allow_nil: true
-
- before_destroy :cancel_stripe_subscription
+ validates :tax_percent, numericality: { greater_than_or_equal_to: 0 }, allow_nil: true,
+ format: { with: /\A\d+(?:\.\d{0,4})?\z/ }
+ # before_save :nil_if_blank
+ before_update :update_stripe_subscription
+ # before_destroy :destroy_stripe_subscription
+ before_save :check_for_upgrade
+ after_save :handle_upgrade
+
+ STATUSES = ['trialing', 'active', 'past_due', 'canceled', 'unpaid']
+
+ def self.from_stripe(stripe_subscription, customer, plan)
+ subscription = Subscription.find_or_create_by(stripe_id: stripe_subscription.id) do |s|
+ s.customer = customer
+ s.plan = plan
+ s.application_fee_percent = stripe_subscription.application_fee_percent
+ s.quantity = stripe_subscription.quantity
+ s.tax_percent = stripe_subscription.tax_percent
+ s.trial_end = stripe_subscription.trial_end
+ s.coupon = Coupon.find_by(stripe_id: stripe_subscription.discount.coupon.id) if stripe_subscription.discount.present?
+ s.status = stripe_subscription.status
+ end
+ return subscription
+ end
+
+ def period_start
+ invoice = invoices.last
+ if invoice.present?
+ return invoice.period_start
+ end
+ return created_at
+ end
+
+ def period_end
+ invoice = invoices.last
+ if invoice.present?
+ return invoice.period_end
+ end
+ return plan.period_days_from(period_start)
+ end
+
+ def quantity
+ self[:quantity] || 1
+ end
+
+ def stripe_trial_end
+ return 'now' if self.end_trial_now
+ return self.trial_end.to_i if self.trial_end.present?
+ return nil
+ end
+
+ def end_trial_now
+ @end_trial_now || false
+ end
+
+ def end_trial_now=(val)
+ @end_trial_now = val
+ end
+
+ def upgraded
+ @upgraded || false
+ end
+
+ def upgraded=(val)
+ @upgraded = val
+ end
+
+ def discount_for_plan(plan)
+ amount_off = 0
+ if self.coupon.percent_off.present?
+ amount_off = (self.coupon.percent_off.to_f / 100.0) * plan.amount.to_f
+ elsif self.coupon.amount_off.present?
+ amount_off = self.coupon.amount_off
+ end
+ return amount_off
+ end
+
private
+
+ # def nil_if_blank
+ # self.trial_end = nil if self.trial_end.blank?
+ # end
+
+ def check_for_upgrade
+ if plan_id_changed?
+ old_plan = Plan.find(plan_id_was) if plan_id_was.present?
+ self.upgraded = true if old_plan.nil? || old_plan.order < plan.order
+ end
+ end
+
+ def handle_upgrade
+ if self.upgraded
+ if Tang.delayed_email
+ SubscriptionMailer.upgraded(self).deliver_later
+ else
+ SubscriptionMailer.upgraded(self).deliver_now
+ end
+ end
+ end
+
+ def update_stripe_subscription
+ UpdateSubscription.call(self)
+ end
def cancel_stripe_subscription
CancelSubscription.call(self)
end
end