feat: Complete email notifications system with comprehensive functionality

- Implement comprehensive email notification system for ticket purchases and event reminders
- Add event reminder job with configurable scheduling
- Enhance ticket mailer with QR code generation and proper formatting
- Update order model with email delivery tracking
- Add comprehensive test coverage for all email functionality
- Configure proper mailer settings and disable annotations
- Update backlog to reflect completed email features

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
kbe
2025-09-06 20:21:01 +02:00
parent e983b68834
commit ce0752bbda
19 changed files with 462 additions and 270 deletions

View File

@@ -56,7 +56,7 @@ class EmailNotificationsIntegrationTest < ActionDispatch::IntegrationTest
test "sends purchase confirmation email when order is marked as paid" do
# Mock PDF generation to avoid QR code issues
@ticket.stubs(:to_pdf).returns("fake_pdf_content")
assert_emails 1 do
@order.mark_as_paid!
end
@@ -78,12 +78,12 @@ class EmailNotificationsIntegrationTest < ActionDispatch::IntegrationTest
end
email = ActionMailer::Base.deliveries.last
assert_equal [@user.email], email.to
assert_equal [ @user.email ], email.to
assert_equal "Rappel : #{@event.name} dans une semaine", email.subject
end
test "event reminder job schedules emails for users with tickets" do
# Setup: mark order as paid and activate tickets
# Setup: mark order as paid and activate tickets
@ticket.stubs(:to_pdf).returns("fake_pdf_content")
@order.mark_as_paid!
@@ -95,7 +95,7 @@ class EmailNotificationsIntegrationTest < ActionDispatch::IntegrationTest
assert_equal 1, ActionMailer::Base.deliveries.size
email = ActionMailer::Base.deliveries.last
assert_equal [@user.email], email.to
assert_equal [ @user.email ], email.to
assert_match "une semaine", email.subject
end
end
end

View File

@@ -23,9 +23,9 @@ class EventReminderJobTest < ActiveJob::TestCase
test "logs error when mailer fails" do
# Mock a failing mailer
TicketMailer.stubs(:event_reminder).raises(StandardError.new("Test error"))
Rails.logger.expects(:error).with(regexp_matches(/Failed to send event reminder/))
EventReminderJob.perform_now(@event.id, 7)
end
end
end

View File

@@ -9,7 +9,7 @@ class EventReminderSchedulerJobTest < ActiveJob::TestCase
# Set event to start in exactly 7 days
@event.update(start_time: 7.days.from_now.beginning_of_day + 10.hours)
assert_enqueued_with(job: EventReminderJob, args: [@event.id, 7]) do
assert_enqueued_with(job: EventReminderJob, args: [ @event.id, 7 ]) do
EventReminderSchedulerJob.perform_now
end
end
@@ -18,7 +18,7 @@ class EventReminderSchedulerJobTest < ActiveJob::TestCase
# Set event to start tomorrow
@event.update(start_time: 1.day.from_now.beginning_of_day + 20.hours)
assert_enqueued_with(job: EventReminderJob, args: [@event.id, 1]) do
assert_enqueued_with(job: EventReminderJob, args: [ @event.id, 1 ]) do
EventReminderSchedulerJob.perform_now
end
end
@@ -27,7 +27,7 @@ class EventReminderSchedulerJobTest < ActiveJob::TestCase
# Set event to start today
@event.update(start_time: Time.current.beginning_of_day + 21.hours)
assert_enqueued_with(job: EventReminderJob, args: [@event.id, 0]) do
assert_enqueued_with(job: EventReminderJob, args: [ @event.id, 0 ]) do
EventReminderSchedulerJob.perform_now
end
end
@@ -47,4 +47,4 @@ class EventReminderSchedulerJobTest < ActiveJob::TestCase
EventReminderSchedulerJob.perform_now
end
end
end
end

View File

@@ -21,11 +21,11 @@ class TicketMailerTest < ActionMailer::TestCase
email.deliver_now
end
assert_equal ["no-reply@aperonight.fr"], email.from
assert_equal [@user.email], email.to
assert_equal [ "no-reply@aperonight.fr" ], email.from
assert_equal [ @user.email ], email.to
assert_equal "Confirmation d'achat - #{@event.name}", email.subject
assert_match @event.name, email.body.to_s
assert_match @user.email.split('@').first, email.body.to_s
assert_match @user.email.split("@").first, email.body.to_s
end
test "purchase confirmation single ticket email" do
@@ -38,11 +38,11 @@ class TicketMailerTest < ActionMailer::TestCase
email.deliver_now
end
assert_equal ["no-reply@aperonight.fr"], email.from
assert_equal [@ticket.user.email], email.to
assert_equal [ "no-reply@aperonight.fr" ], email.from
assert_equal [ @ticket.user.email ], email.to
assert_equal "Confirmation d'achat - #{@ticket.event.name}", email.subject
assert_match @ticket.event.name, email.body.to_s
assert_match @ticket.user.email.split('@').first, email.body.to_s
assert_match @ticket.user.email.split("@").first, email.body.to_s
end
test "event reminder email one week before" do
@@ -56,8 +56,8 @@ class TicketMailerTest < ActionMailer::TestCase
email.deliver_now
end
assert_equal ["no-reply@aperonight.fr"], email.from
assert_equal [@user.email], email.to
assert_equal [ "no-reply@aperonight.fr" ], email.from
assert_equal [ @user.email ], email.to
assert_equal "Rappel : #{@event.name} dans une semaine", email.subject
assert_match "une semaine", email.body.to_s
assert_match @event.name, email.body.to_s
@@ -101,4 +101,4 @@ class TicketMailerTest < ActionMailer::TestCase
assert_equal "Rappel : #{@event.name} dans 3 jours", email.subject
assert_match "3 jours", email.body.to_s
end
end
end

View File

@@ -8,31 +8,31 @@ class OrderEmailTest < ActiveSupport::TestCase
test "sends purchase confirmation email when order is marked as paid" do
# Mock the mailer to capture the call
TicketMailer.expects(:purchase_confirmation_order).with(@order).returns(stub(deliver_now: true))
@order.mark_as_paid!
assert_equal "paid", @order.status
end
test "activates all tickets when order is marked as paid" do
@order.tickets.update_all(status: "reserved")
# Mock the mailer to avoid actual email sending
TicketMailer.stubs(:purchase_confirmation_order).returns(stub(deliver_now: true))
@order.mark_as_paid!
assert @order.tickets.all? { |ticket| ticket.status == "active" }
end
test "email sending failure does not prevent order completion" do
# Mock mailer to raise an error
TicketMailer.stubs(:purchase_confirmation_order).raises(StandardError.new("Email error"))
# Should not raise error - email failure is logged but doesn't fail the payment
@order.mark_as_paid!
# Order should still be marked as paid even if email fails
assert_equal "paid", @order.reload.status
end
end
end