develop #3
14
.env.example
14
.env.example
@@ -1,18 +1,18 @@
|
|||||||
# Application data
|
# Application data
|
||||||
RAILS_ENV=development
|
RAILS_ENV=production
|
||||||
SECRET_KEY_BASE=a3f5c6e7b8d9e0f1a2b3c4d5e6f7g8h9i0j1k2l3m4n5o6p7q8r9s0t1u2v3w4x5y6z7
|
SECRET_KEY_BASE=a3f5c6e7b8d9e0f1a2b3c4d5e6f7g8h9i0j1k2l3m4n5o6p7q8r9s0t1u2v3w4x5y6z7
|
||||||
DEVISE_SECRET_KEY=your_devise_secret_key_here
|
DEVISE_SECRET_KEY=your_devise_secret_key_here
|
||||||
APP_NAME=Aperonight
|
APP_NAME=Aperonight
|
||||||
|
|
||||||
# Database Configuration for production and development
|
# Database Configuration for production and development
|
||||||
DB_HOST=localhost
|
# DB_HOST=127.0.0.1
|
||||||
|
# DB_PORT=3306
|
||||||
DB_ROOT_PASSWORD=root
|
DB_ROOT_PASSWORD=root
|
||||||
DB_DATABASE=aperonight
|
DB_DATABASE=aperonight
|
||||||
DB_USERNAME=root
|
DB_USERNAME=root
|
||||||
DB_PASSWORD=root
|
DB_PASSWORD=root
|
||||||
|
|
||||||
# Test database
|
# Test database
|
||||||
DB_TEST_ADAPTER=sqlite3
|
|
||||||
DB_TEST_DATABASE=aperonight_test
|
DB_TEST_DATABASE=aperonight_test
|
||||||
DB_TEST_USERNAME=root
|
DB_TEST_USERNAME=root
|
||||||
DB_TEST_USERNAME=root
|
DB_TEST_USERNAME=root
|
||||||
@@ -28,14 +28,6 @@ SMTP_PORT=1025
|
|||||||
# SMTP_DOMAIN=localhost
|
# SMTP_DOMAIN=localhost
|
||||||
SMTP_AUTHENTICATION=plain
|
SMTP_AUTHENTICATION=plain
|
||||||
SMTP_ENABLE_STARTTLS=false
|
SMTP_ENABLE_STARTTLS=false
|
||||||
|
|
||||||
# Production SMTP Configuration (set these in .env.production)
|
|
||||||
# SMTP_ADDRESS=smtp.example.com
|
|
||||||
# SMTP_PORT=587
|
|
||||||
# SMTP_USERNAME=your_smtp_username
|
|
||||||
# SMTP_PASSWORD=your_smtp_password
|
|
||||||
# SMTP_AUTHENTICATION=plain
|
|
||||||
# SMTP_DOMAIN=example.com
|
|
||||||
# SMTP_STARTTLS=true
|
# SMTP_STARTTLS=true
|
||||||
|
|
||||||
# Application variables
|
# Application variables
|
||||||
|
|||||||
@@ -7,11 +7,16 @@ class TicketMailer < ApplicationMailer
|
|||||||
|
|
||||||
# Generate PDF attachments for all tickets
|
# Generate PDF attachments for all tickets
|
||||||
@tickets.each do |ticket|
|
@tickets.each do |ticket|
|
||||||
pdf = ticket.to_pdf
|
begin
|
||||||
attachments["ticket-#{@event.name.parameterize}-#{ticket.qr_code[0..7]}.pdf"] = {
|
pdf = ticket.to_pdf
|
||||||
mime_type: "application/pdf",
|
attachments["ticket-#{@event.name.parameterize}-#{ticket.qr_code[0..7]}.pdf"] = {
|
||||||
content: pdf
|
mime_type: "application/pdf",
|
||||||
}
|
content: pdf
|
||||||
|
}
|
||||||
|
rescue StandardError => e
|
||||||
|
Rails.logger.error "Failed to generate PDF for ticket #{ticket.id}: #{e.message}"
|
||||||
|
# Continue without PDF attachment rather than failing the entire email
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
mail(
|
mail(
|
||||||
@@ -27,11 +32,16 @@ class TicketMailer < ApplicationMailer
|
|||||||
@event = ticket.event
|
@event = ticket.event
|
||||||
|
|
||||||
# Generate PDF attachment
|
# Generate PDF attachment
|
||||||
pdf = @ticket.to_pdf
|
begin
|
||||||
attachments["ticket-#{@event.name.parameterize}-#{@ticket.qr_code[0..7]}.pdf"] = {
|
pdf = @ticket.to_pdf
|
||||||
mime_type: "application/pdf",
|
attachments["ticket-#{@event.name.parameterize}-#{@ticket.qr_code[0..7]}.pdf"] = {
|
||||||
content: pdf
|
mime_type: "application/pdf",
|
||||||
}
|
content: pdf
|
||||||
|
}
|
||||||
|
rescue StandardError => e
|
||||||
|
Rails.logger.error "Failed to generate PDF for ticket #{@ticket.id}: #{e.message}"
|
||||||
|
# Continue without PDF attachment rather than failing the entire email
|
||||||
|
end
|
||||||
|
|
||||||
mail(
|
mail(
|
||||||
to: @user.email,
|
to: @user.email,
|
||||||
|
|||||||
@@ -75,9 +75,16 @@ class Order < ApplicationRecord
|
|||||||
transaction do
|
transaction do
|
||||||
update!(status: "paid")
|
update!(status: "paid")
|
||||||
tickets.update_all(status: "active")
|
tickets.update_all(status: "active")
|
||||||
|
end
|
||||||
# Send purchase confirmation email
|
|
||||||
|
# Send purchase confirmation email outside the transaction
|
||||||
|
# so that payment completion isn't affected by email failures
|
||||||
|
begin
|
||||||
TicketMailer.purchase_confirmation_order(self).deliver_now
|
TicketMailer.purchase_confirmation_order(self).deliver_now
|
||||||
|
rescue StandardError => e
|
||||||
|
Rails.logger.error "Failed to send purchase confirmation email for order #{id}: #{e.message}"
|
||||||
|
Rails.logger.error e.backtrace.join("\n")
|
||||||
|
# Don't re-raise the error - payment should still succeed
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -74,18 +74,21 @@ class TicketPdfGenerator
|
|||||||
raise "Ticket QR code is missing"
|
raise "Ticket QR code is missing"
|
||||||
end
|
end
|
||||||
|
|
||||||
qr_code_data = {
|
# Build QR code data with safe association loading
|
||||||
ticket_id: ticket.id,
|
qr_code_data = build_qr_code_data(ticket)
|
||||||
qr_code: ticket.qr_code,
|
|
||||||
event_id: ticket.event&.id,
|
|
||||||
user_id: ticket.user&.id
|
|
||||||
}.compact.to_json
|
|
||||||
|
|
||||||
# Validate QR code data before creating QR code
|
# Validate QR code data before creating QR code
|
||||||
if qr_code_data.blank? || qr_code_data == "{}"
|
if qr_code_data.blank? || qr_code_data == "{}"
|
||||||
|
Rails.logger.error "QR code data is empty: ticket_id=#{ticket.id}, qr_code=#{ticket.qr_code}, event_id=#{ticket.ticket_type&.event_id}, user_id=#{ticket.order&.user_id}"
|
||||||
raise "QR code data is empty or invalid"
|
raise "QR code data is empty or invalid"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Ensure qr_code_data is a proper string for QR code generation
|
||||||
|
unless qr_code_data.is_a?(String) && qr_code_data.length > 2
|
||||||
|
Rails.logger.error "QR code data is not a valid string: #{qr_code_data.inspect} (class: #{qr_code_data.class})"
|
||||||
|
raise "QR code data must be a valid string"
|
||||||
|
end
|
||||||
|
|
||||||
qrcode = RQRCode::QRCode.new(qr_code_data)
|
qrcode = RQRCode::QRCode.new(qr_code_data)
|
||||||
pdf.print_qr_code(qrcode, extent: 120, align: :center)
|
pdf.print_qr_code(qrcode, extent: 120, align: :center)
|
||||||
|
|
||||||
@@ -110,4 +113,36 @@ class TicketPdfGenerator
|
|||||||
pdf.text "Generated on #{Time.current.strftime('%B %d, %Y at %I:%M %p')}", align: :center
|
pdf.text "Generated on #{Time.current.strftime('%B %d, %Y at %I:%M %p')}", align: :center
|
||||||
end.render
|
end.render
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def build_qr_code_data(ticket)
|
||||||
|
# Try multiple approaches to get valid QR code data
|
||||||
|
begin
|
||||||
|
# Primary approach: full JSON with all data
|
||||||
|
data = {
|
||||||
|
ticket_id: ticket.id,
|
||||||
|
qr_code: ticket.qr_code,
|
||||||
|
event_id: ticket.ticket_type&.event_id,
|
||||||
|
user_id: ticket.order&.user_id
|
||||||
|
}.compact
|
||||||
|
|
||||||
|
# Ensure we have the minimum required data
|
||||||
|
if data[:ticket_id] && data[:qr_code]
|
||||||
|
return data.to_json
|
||||||
|
end
|
||||||
|
rescue StandardError => e
|
||||||
|
Rails.logger.warn "Failed to build complex QR data: #{e.message}"
|
||||||
|
end
|
||||||
|
|
||||||
|
# Fallback approach: just use the ticket's QR code string
|
||||||
|
begin
|
||||||
|
return ticket.qr_code.to_s if ticket.qr_code.present?
|
||||||
|
rescue StandardError => e
|
||||||
|
Rails.logger.warn "Failed to use ticket QR code: #{e.message}"
|
||||||
|
end
|
||||||
|
|
||||||
|
# Final fallback: simple ticket identifier
|
||||||
|
"TICKET-#{ticket.id}"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -25,6 +25,6 @@ module Aperonight
|
|||||||
# config.eager_load_paths << Rails.root.join("extras")
|
# config.eager_load_paths << Rails.root.join("extras")
|
||||||
|
|
||||||
config.i18n.load_path += Dir[Rails.root.join("my", "locales", "*.{rb,yml}")]
|
config.i18n.load_path += Dir[Rails.root.join("my", "locales", "*.{rb,yml}")]
|
||||||
config.i18n.default_locale = :fr
|
# config.i18n.default_locale = :fr
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user