require 'active_support/concern' module Tang module Customer extend ActiveSupport::Concern included do belongs_to :coupon, class_name: 'Tang::Coupon', optional: true belongs_to :subscription_coupon, class_name: 'Tang::Coupon', optional: true has_many :cards, class_name: 'Tang::Card', foreign_key: 'customer_id', dependent: :destroy has_many :subscriptions, class_name: 'Tang::Subscription', foreign_key: 'customer_id', dependent: :destroy has_many :invoices, class_name: 'Tang::Invoice', foreign_key: 'customer_id', dependent: :destroy has_many :charges, through: :invoices, class_name: 'Tang::Charge', dependent: :destroy before_save :nil_if_blank # before_update :update_stripe_customer before_destroy :delete_stripe_customer validates :stripe_id, uniqueness: true, allow_nil: true, if: :stripe_id_changed? validates :account_balance, numericality: { only_integer: true }, allow_nil: true define_method :admin? do self.respond_to?(:role) && self.role == 'admin' end define_method :stripe_enabled? do true end end def self.table_name return Tang.customer_class.to_s.downcase.pluralize end def self.search(query) customers = Tang.customer_class.none if query.present? q = "%#{query.downcase}%" customer_table = ActiveRecord::Base.connection.quote_table_name(Customer.table_name) customers = Tang.customer_class. joins(:subscriptions, :coupon). where.not(stripe_id: nil). where("lower(#{customer_table}.stripe_id) like ? or lower(#{customer_table}.email) like ? or lower(tang_subscriptions.stripe_id) like ? or lower(tang_coupons.stripe_id) like ?", q, q, q, q). distinct end return customers end def card self.cards.order(:created_at).last end def subscription @subscription ||= self.subscriptions.where.not(status: :canceled).order(:created_at).last end def generate_password self.password = Devise.friendly_token.first(8) end def update_card_from_stripe(stripe_card) my_card = self.card.present? ? self.card : Card.new(customer: self) my_card.update_from_stripe(stripe_card) end def update_subscription_end(subscription) self.active_until = subscription.period_end self.save! end # NOTE: May be causing memory bloat def subscribed_to?(stripe_id) subscription_plan = self.subscription.plan if self.subscription.present? if subscription_plan.present? return true if subscription_plan.stripe_id == stripe_id if Tang.plan_inheritance other_plan = Plan.find_by(stripe_id: stripe_id) return true if other_plan.present? && subscription_plan.order >= other_plan.order end end return false end def coupon_end if coupon.present? && coupon.duration != 'forever' end return nil end def has_coupon? if self.subscription.present? if self.subscription.coupon.present? return true end end return self.coupon.present? end def has_subscription_coupon? return self.subscription.present? && self.subscription.coupon.present? 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.description = nil if self.description.blank? end def update_stripe_customer UpdateCustomer.call(self) end def delete_stripe_customer DeleteCustomer.call(self) end end end