feat: improve seo urls?
This commit is contained in:
@@ -1,95 +1,24 @@
|
||||
# Legacy tickets controller - redirects to new order system
|
||||
# Tickets controller - handles ticket viewing and downloads with SEO-friendly URLs
|
||||
#
|
||||
# This controller now primarily handles legacy redirects and backward compatibility
|
||||
# Most ticket creation functionality has been moved to OrdersController
|
||||
# This controller manages individual ticket display and downloads
|
||||
# Uses event-slug-ticket-id format for SEO-friendly URLs
|
||||
class TicketsController < ApplicationController
|
||||
before_action :authenticate_user!, only: [ :payment_success, :payment_cancel, :show, :ticket_view, :download_ticket ]
|
||||
before_action :set_event, only: [ :checkout, :retry_payment ]
|
||||
|
||||
# Redirect to order-based checkout
|
||||
def checkout
|
||||
# Check for draft order
|
||||
if session[:draft_order_id].present?
|
||||
order = current_user.orders.find_by(id: session[:draft_order_id], status: "draft")
|
||||
if order.present?
|
||||
redirect_to order_checkout_path(order)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
# No order found
|
||||
@event = Event.includes(:ticket_types).find(params[:id])
|
||||
redirect_to event_path(@event.slug, @event), alert: "Aucun billet en attente de paiement"
|
||||
end
|
||||
|
||||
# Redirect to order-based payment success
|
||||
def payment_success
|
||||
redirect_to order_payment_success_path(session_id: params[:session_id])
|
||||
end
|
||||
|
||||
# Redirect to order-based payment cancel
|
||||
def payment_cancel
|
||||
redirect_to order_payment_cancel_path
|
||||
end
|
||||
|
||||
# Redirect retry payment to order system
|
||||
def retry_payment
|
||||
@event = Event.includes(:ticket_types).find(params[:id])
|
||||
|
||||
# Look for draft order for this event
|
||||
order = current_user.orders.find_by(event: @event, status: "draft")
|
||||
|
||||
if order&.can_retry_payment?
|
||||
redirect_to retry_payment_order_path(order)
|
||||
else
|
||||
redirect_to event_path(@event.slug, @event),
|
||||
alert: "Aucune commande disponible pour un nouveau paiement"
|
||||
end
|
||||
end
|
||||
before_action :authenticate_user!
|
||||
before_action :set_ticket_from_seo_params, only: [:show, :view, :download, :retry_payment]
|
||||
|
||||
# Display ticket details
|
||||
def show
|
||||
@ticket = Ticket.joins(order: :user).includes(:event, :ticket_type, order: :user).find_by(
|
||||
tickets: { id: params[:ticket_id] },
|
||||
orders: { user_id: current_user.id }
|
||||
)
|
||||
@event = @ticket.event
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
redirect_to dashboard_path, alert: "Billet non trouvé"
|
||||
end
|
||||
|
||||
# Display ticket in PDF-like format
|
||||
def ticket_view
|
||||
@ticket = Ticket.joins(order: :user).includes(:event, :ticket_type, order: :user).find_by(
|
||||
tickets: { id: params[:ticket_id] },
|
||||
orders: { user_id: current_user.id }
|
||||
)
|
||||
|
||||
if @ticket.nil?
|
||||
redirect_to dashboard_path, alert: "Billet non trouvé ou vous n'avez pas l'autorisation d'accéder à ce billet"
|
||||
return
|
||||
end
|
||||
|
||||
def view
|
||||
@event = @ticket.event
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
redirect_to dashboard_path, alert: "Billet non trouvé"
|
||||
end
|
||||
|
||||
# Download PDF ticket - only accessible by ticket owner
|
||||
# User must be authenticated to download ticket
|
||||
# TODO: change ID to an unique identifier (UUID)
|
||||
def download_ticket
|
||||
# Find ticket and ensure it belongs to current user
|
||||
@ticket = Ticket.joins(order: :user).includes(:event, :ticket_type, order: :user).find_by(
|
||||
tickets: { id: params[:ticket_id] },
|
||||
orders: { user_id: current_user.id }
|
||||
)
|
||||
|
||||
if @ticket.nil?
|
||||
redirect_to dashboard_path, alert: "Billet non trouvé ou vous n'avez pas l'autorisation d'accéder à ce billet"
|
||||
return
|
||||
end
|
||||
|
||||
def download
|
||||
# Generate PDF using Grover
|
||||
begin
|
||||
Rails.logger.info "Starting PDF generation for ticket ID: #{@ticket.id}"
|
||||
@@ -103,96 +32,96 @@ class TicketsController < ApplicationController
|
||||
|
||||
Rails.logger.info "HTML template rendered successfully, length: #{html.length}"
|
||||
|
||||
# Try to load and use Grover
|
||||
begin
|
||||
Rails.logger.info "Attempting to load Grover gem"
|
||||
# Configure Grover options for PDF generation
|
||||
pdf_options = {
|
||||
format: 'A4',
|
||||
margin: {
|
||||
top: '0.5in',
|
||||
bottom: '0.5in',
|
||||
left: '0.5in',
|
||||
right: '0.5in'
|
||||
},
|
||||
print_background: true,
|
||||
display_header_footer: false,
|
||||
prefer_css_page_size: true,
|
||||
launch_args: ["--no-sandbox", "--disable-setuid-sandbox"] # For better compatibility
|
||||
}
|
||||
|
||||
# Try different approaches to load grover
|
||||
begin
|
||||
require "bundler"
|
||||
Bundler.require(:default, Rails.env)
|
||||
Rails.logger.info "Bundler required gems successfully"
|
||||
rescue => bundler_error
|
||||
Rails.logger.warn "Bundler require failed: #{bundler_error.message}"
|
||||
end
|
||||
# Generate PDF
|
||||
pdf = Grover.new(html, pdf_options).to_pdf
|
||||
|
||||
Rails.logger.info "PDF generation completed for ticket ID: #{@ticket.id}"
|
||||
|
||||
# Direct path approach using bundle show
|
||||
grover_gem_path = `bundle show grover`.strip
|
||||
grover_path = File.join(grover_gem_path, "lib", "grover")
|
||||
|
||||
if File.exist?(grover_path + ".rb")
|
||||
Rails.logger.info "Loading Grover from direct path: #{grover_path}"
|
||||
require grover_path
|
||||
else
|
||||
Rails.logger.error "Grover not found at path: #{grover_path}"
|
||||
raise LoadError, "Grover gem not available at expected path"
|
||||
end
|
||||
|
||||
Rails.logger.info "Creating Grover instance with options"
|
||||
grover = Grover.new(html,
|
||||
format: "A6",
|
||||
margin: {
|
||||
top: "10mm",
|
||||
bottom: "10mm",
|
||||
left: "10mm",
|
||||
right: "10mm"
|
||||
},
|
||||
prefer_css_page_size: true,
|
||||
emulate_media: "print",
|
||||
cache: false,
|
||||
launch_args: [ "--no-sandbox", "--disable-setuid-sandbox" ] # For better compatibility
|
||||
)
|
||||
Rails.logger.info "Grover instance created successfully"
|
||||
|
||||
pdf_content = grover.to_pdf
|
||||
Rails.logger.info "PDF generated successfully, length: #{pdf_content.length}"
|
||||
|
||||
# Send PDF as download
|
||||
send_data pdf_content,
|
||||
filename: "ticket_#{@ticket.id}_#{@ticket.event.name.parameterize}.pdf",
|
||||
type: "application/pdf",
|
||||
disposition: "attachment"
|
||||
rescue LoadError => grover_error
|
||||
Rails.logger.error "Failed to load Grover: #{grover_error.message}"
|
||||
# Fallback: return HTML instead of PDF
|
||||
send_data html,
|
||||
filename: "ticket_#{@ticket.id}_#{@ticket.event.name.parameterize}.html",
|
||||
type: "text/html",
|
||||
disposition: "attachment"
|
||||
end
|
||||
# Send PDF as download with SEO-friendly filename
|
||||
send_data pdf,
|
||||
filename: "billet-#{@ticket.event.slug}-#{@ticket.id}.pdf",
|
||||
type: 'application/pdf',
|
||||
disposition: 'attachment'
|
||||
rescue => e
|
||||
Rails.logger.error "Error generating ticket PDF with Grover:"
|
||||
Rails.logger.error "Message: #{e.message}"
|
||||
Rails.logger.error "Backtrace: #{e.backtrace.join("\n")}"
|
||||
redirect_to dashboard_path, alert: "Erreur lors de la génération du billet"
|
||||
Rails.logger.error "PDF generation failed for ticket ID: #{@ticket.id} - Error: #{e.message}"
|
||||
Rails.logger.error e.backtrace.join("\n")
|
||||
|
||||
redirect_to view_ticket_path(event_slug: @ticket.event.slug, ticket_id: @ticket.id),
|
||||
alert: "Erreur lors de la génération du PDF. Veuillez réessayer."
|
||||
end
|
||||
rescue ActiveRecord::RecordNotFound => e
|
||||
Rails.logger.error "ActiveRecord::RecordNotFound error: #{e.message}"
|
||||
redirect_to dashboard_path, alert: "Billet non trouvé"
|
||||
rescue => e
|
||||
Rails.logger.error "Unexpected error in download_ticket action:"
|
||||
Rails.logger.error "Message: #{e.message}"
|
||||
Rails.logger.error "Backtrace: #{e.backtrace.join("\n")}"
|
||||
redirect_to dashboard_path, alert: "Erreur lors de la génération du billet"
|
||||
end
|
||||
|
||||
# Redirect retry payment to order system
|
||||
def retry_payment
|
||||
# Look for draft order for this ticket's event
|
||||
order = current_user.orders.find_by(event: @ticket.event, status: "draft")
|
||||
|
||||
if order&.can_retry_payment?
|
||||
year = order.event.start_time.year
|
||||
month = format("%02d", order.event.start_time.month)
|
||||
redirect_to event_checkout_path(year: year, month: month, slug: order.event.slug)
|
||||
else
|
||||
redirect_to seo_event_path(@ticket.event),
|
||||
alert: "Aucune commande disponible pour un nouveau paiement"
|
||||
end
|
||||
end
|
||||
|
||||
# Legacy redirects for backward compatibility
|
||||
def payment_success
|
||||
redirect_to booking_payment_success_path(session_id: params[:session_id])
|
||||
end
|
||||
|
||||
def payment_cancel
|
||||
redirect_to booking_payment_cancelled_path
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_event
|
||||
event_id = params[:id] || session[:event_id]
|
||||
def set_ticket_from_seo_params
|
||||
# Parse event_slug and ticket_id from the SEO-friendly format: event-slug-123
|
||||
slug_and_id = params[:event_slug_ticket_id] || "#{params[:event_slug]}-#{params[:ticket_id]}"
|
||||
|
||||
# Split by last dash to separate event slug from ticket ID
|
||||
parts = slug_and_id.split('-')
|
||||
ticket_id = parts.pop
|
||||
event_slug = parts.join('-')
|
||||
|
||||
Rails.logger.debug "TicketsController#set_event - params[:id]: #{params[:id].inspect}, session[:event_id]: #{session[:event_id].inspect}"
|
||||
# Find ticket and ensure it belongs to current user
|
||||
@ticket = Ticket.joins(order: :user)
|
||||
.includes(:event, :ticket_type, order: :user)
|
||||
.joins(:event)
|
||||
.where(
|
||||
tickets: { id: ticket_id },
|
||||
orders: { user_id: current_user.id },
|
||||
events: { slug: event_slug }
|
||||
)
|
||||
.first
|
||||
|
||||
unless event_id
|
||||
Rails.logger.error "TicketsController#set_event - No event ID found"
|
||||
redirect_to events_path, alert: "Aucun événement spécifié"
|
||||
return
|
||||
unless @ticket
|
||||
redirect_to dashboard_path, alert: "Billet non trouvé ou vous n'avez pas l'autorisation d'accéder à ce billet"
|
||||
end
|
||||
|
||||
@event = Event.includes(:ticket_types).find(event_id)
|
||||
Rails.logger.debug "TicketsController#set_event - Found event: #{@event.id} - #{@event.name}"
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
Rails.logger.error "TicketsController#set_event - Event not found with ID: #{event_id}"
|
||||
redirect_to events_path, alert: "Événement non trouvé"
|
||||
end
|
||||
end
|
||||
|
||||
# Generate SEO-friendly path for an event
|
||||
def seo_event_path(event)
|
||||
year = event.start_time.year
|
||||
month = format("%02d", event.start_time.month)
|
||||
event_path(year: year, month: month, slug: event.slug)
|
||||
end
|
||||
helper_method :seo_event_path
|
||||
end
|
||||
Reference in New Issue
Block a user