fix(promotion code): Cap the minimum invoice for Stripe

Stripe does not support negative invoices, so to
allow correct invoice generation, we apply dismiss
negative invoices.
This commit is contained in:
kbe
2025-09-29 23:55:21 +02:00
parent 635644b55a
commit 66fffa8676
3 changed files with 351 additions and 62 deletions

View File

@@ -130,11 +130,16 @@ class OrdersController < ApplicationController
if params[:promotion_code].present?
promotion_code = PromotionCode.valid.find_by(code: params[:promotion_code].upcase)
if promotion_code
# Apply the promotion code to the order
@order.promotion_codes << promotion_code
@order.calculate_total!
@total_amount = @order.total_amount_cents
flash.now[:notice] = "Code promotionnel appliqué: #{promotion_code.code}"
# Check if promotion code is already applied to this order
if @order.promotion_codes.include?(promotion_code)
flash.now[:alert] = "Ce code promotionnel est déjà appliqué à cette commande"
else
# Apply the promotion code to the order
@order.promotion_codes << promotion_code
@order.calculate_total!
@total_amount = @order.total_amount_cents
flash.now[:notice] = "Code promotionnel appliqué: #{promotion_code.code}"
end
else
flash.now[:alert] = "Code promotionnel invalide"
end
@@ -302,7 +307,14 @@ class OrdersController < ApplicationController
end
def create_stripe_session
# Calculate the discount amount per ticket to distribute the promotion evenly
total_tickets = @order.tickets.count
discount_per_ticket = @order.discount_amount_cents / total_tickets if total_tickets > 0
line_items = @order.tickets.map do |ticket|
# Apply discount proportionally to each ticket
discounted_price = [ticket.price_cents - discount_per_ticket.to_i, 0].max
{
price_data: {
currency: "eur",
@@ -310,7 +322,7 @@ class OrdersController < ApplicationController
name: "#{@order.event.name} - #{ticket.ticket_type.name}",
description: ticket.ticket_type.description
},
unit_amount: ticket.price_cents
unit_amount: discounted_price
},
quantity: 1
}

View File

@@ -21,6 +21,9 @@ class Order < ApplicationRecord
validates :payment_attempts, presence: true,
numericality: { greater_than_or_equal_to: 0 }
# Custom validation to prevent duplicate promotion codes
validate :no_duplicate_promotion_codes
# Stripe invoice ID for accounting records
attr_accessor :stripe_invoice_id
@@ -188,4 +191,12 @@ class Order < ApplicationRecord
def draft?
status == "draft"
end
# Prevent duplicate promotion codes on the same order
def no_duplicate_promotion_codes
promotion_code_ids = promotion_codes.map(&:id)
if promotion_code_ids.size != promotion_code_ids.uniq.size
errors.add(:promotion_codes, "ne peuvent pas contenir de codes en double")
end
end
end