feat(promotion code): Promotion code system done

I added the features for users to use promotion code
and for promoters to create on their events.
May be rewrite to discount code?
This commit is contained in:
kbe
2025-09-29 15:25:52 +02:00
parent 72d54e02ab
commit 87ccebf229
19 changed files with 391 additions and 302 deletions

View File

@@ -21,6 +21,7 @@ class Event < ApplicationRecord
has_many :ticket_types
has_many :tickets, through: :ticket_types
has_many :orders
has_many :promotion_codes
# === Callbacks ===
before_validation :geocode_address, if: :should_geocode_address?

View File

@@ -90,10 +90,34 @@ class Order < ApplicationRecord
end
end
# Calculate total from ticket prices only (platform fee deducted from promoter payout)
# Calculate total from ticket prices minus promotion code discounts
def calculate_total!
ticket_total = tickets.sum(:price_cents)
update!(total_amount_cents: ticket_total)
discount_total = promotion_codes.sum(:discount_amount_cents)
# Ensure total doesn't go below zero
final_total = [ticket_total - discount_total, 0].max
update!(total_amount_cents: final_total)
end
# Subtotal amount before discounts
def subtotal_amount_cents
tickets.sum(:price_cents)
end
# Subtotal amount in euros
def subtotal_amount_euros
subtotal_amount_cents / 100.0
end
# Total discount amount from all promotion codes
def discount_amount_cents
promotion_codes.sum(:discount_amount_cents)
end
# Discount amount in euros
def discount_amount_euros
discount_amount_cents / 100.0
end
# Platform fee: €0.50 fixed + 1.5% of ticket price, per ticket

View File

@@ -12,9 +12,28 @@ class PromotionCode < ApplicationRecord
before_create :increment_uses_count
# Associations
belongs_to :user
belongs_to :event
has_many :order_promotion_codes
has_many :orders, through: :order_promotion_codes
# Instance methods
def discount_amount_euros
discount_amount_cents / 100.0
end
def active?
active && (expires_at.nil? || expires_at > Time.current)
end
def expired?
expires_at.present? && expires_at < Time.current
end
def can_be_used?
active? && (usage_limit.nil? || uses_count < usage_limit)
end
private
def increment_uses_count