app/models/tang/coupon.rb in tang-0.0.1 vs app/models/tang/coupon.rb in tang-0.0.8
- old
+ new
@@ -1,5 +1,99 @@
module Tang
class Coupon < ActiveRecord::Base
has_paper_trail
+ # acts_as_paranoid
+
+ has_many :customers, class_name: Tang.customer_class.to_s
+ has_many :subscriptions
+ has_many :invoices
+
+ validates :stripe_id, presence: true
+ validates :stripe_id, uniqueness: true # , if: "deleted_at.nil?"
+ validates :duration, inclusion: { in: %w(once repeating forever) }
+ validates :amount_off, numericality: { only_integer: true, greater_than: 0 }, allow_nil: true
+ validates :currency, presence: true, if: -> { amount_off.present? }
+ validates :duration_in_months, presence: true, numericality: { only_integer: true, greater_than: 0 }, if: :repeating?
+ validates :max_redemptions, numericality: { only_integer: true, greater_than: 0 }, allow_nil: true
+ validates :percent_off, numericality: { only_integer: true, greater_than_or_equal_to: 1, less_than_or_equal_to: 100 },
+ presence: true, if: -> { amount_off.nil? }
+ validates :redeem_by, future: true, if: -> { redeem_by.present? }
+
+ before_create :create_stripe_coupon
+ before_update :update_stripe_coupon
+ before_destroy :delete_stripe_coupon # should be soft delete
+
+ DURATIONS = ['once', 'repeating', 'forever']
+
+ def coupon_valid?
+ # check if expired
+ if self.redeem_by.present?
+ return false if Time.now > self.redeem_by
+ end
+
+ if self.max_redemptions.present?
+ # check if any discounts created
+ end
+
+ return true
+ end
+
+ def formatted_duration
+ if repeating?
+ "for #{duration_in_months} months"
+ else
+ duration
+ end
+ end
+
+ def active_redemptions
+ customer_table = ActiveRecord::Base.connection.quote_table_name(Customer.table_name)
+ Tang.customer_class.
+ joins(:subscriptions).
+ where("#{customer_table}.coupon_id = ? OR tang_subscriptions.coupon_id = ?", self.id, self.id).
+ where.not(tang_subscriptions: { status: :canceled }).
+ uniq
+ end
+
+ def repeating?
+ duration == "repeating"
+ end
+
+ def discount(amount)
+ subtotal = amount
+ if self.percent_off.present?
+ subtotal = amount.to_f * (self.percent_off.to_f / 100.0)
+ elsif self.amount_off.present?
+ subtotal = self.amount_off
+ end
+ return -subtotal.to_f
+ end
+
+ def self.from_stripe(stripe_coupon)
+ coupon = Coupon.find_or_create_by(stripe_id: stripe_coupon.id) do |c|
+ c.percent_off = stripe_coupon.percent_off
+ c.currency = stripe_coupon.currency
+ c.amount_off = stripe_coupon.amount_off
+ c.duration = stripe_coupon.duration
+ c.duration_in_months = stripe_coupon.duration_in_months
+ c.max_redemptions = stripe_coupon.max_redemptions
+ c.redeem_by = stripe_coupon.redeem_by
+ end
+
+ return coupon
+ end
+
+ private
+
+ def create_stripe_coupon
+ CreateCoupon.call(self)
+ end
+
+ def update_stripe_coupon
+ UpdateCoupon.call(self)
+ end
+
+ def delete_stripe_coupon
+ DeleteCoupon.call(self)
+ end
end
end