Spree: Напоминание об оплате

Возникла необходимось в нашем аюрведическом интернет-магазине SpiceGarden.ru сделать напоминание об оплате заказа. Пользователи не редко делают заказ и забывают или тянут с оплатой. Поэтому решили их ограничит всего 5 днями для оплаты. Потом заказ аннулируется.

Сам магазин построен на базе Spree (оно же в свою очередь есть ни что иное как Ruby On Rails). Поэтому добавление такого функционала не представляет ничего сложного. Буквально несколько шагов.

Первым шагом является создание mailer’a, который будет отвечать за отправку писем конкретному владельцу заказа. Для этого запустем генератор Rails, который сгенерит минимально необходимые файлы:

rails generate mailer PaymentNotificationMailer

В итоге работы генератора у нас появились 2 файла: собственно mailer

app/mailers/payment_notification\_mailer.rb

и тесты для него

test/functional/payment_notification\_mailer\_test.rb

А так же директория для шаблонов писем:

app/views/payment_notification_mailer/

Работу с тестами опустим и приступим к настройке mailer’а. Собственно настраивать там особо нечего.

class PaymentNotificationMailer < ActionMailer::Base
  default :from => "SpiceGarden.ru "

  def payment_notification(order, days)
    @order = order
    @user = order.user
    @days = days
    mail :to => @user.email, :subject => "SpiceGarden.ru. Напоминание об оплате заказа"
  end
end

В классе описывается всего один метод, который на вход получает обрабатываемый заказ и кол-во дней, оставшихся до аннулирования заказа.

Далее необходима описать шаблон письма. Письмо будем отсылать только в текстовом формате без html, поэтому нам достаточно только создать один файл:

app/views/payment_notification_mailer/payment_notification.text.erb

Приводить код шаблона не буду.

Все. Mailer у нас настроен. Теперь нужно его как-то вызывать. Поскольку задача у нас периодическая, то создадим задание для cron’a. Для этого в каталоге lib/tasks создаем файл с задачей для Rake, которую будем запускать раз в день. Код задачи:

namespace :notifications do

  desc "Send notification about payments"
  task :payment => :environment do
    Order.where(:state => "complete", :payment_state => "balance_due").order("completed_at").each do |order|
      days_for_payment = 5 - (Time.now - order.completed_at).to_i / 3600 / 24

      # Close expired orders
      if days_for_payment < 1
        puts "Order #{order.number} is CANCELED !!!"
        order.cancel!
        next
      end

      days_for_payment = 1 if days_for_payment < 1

      # Send notification about payment waiting
      puts "ORDER: #{order.number}\tDays: #{days_for_payment}\tSEND #{order.email}"
      PaymentNotificationMailer.payment_notification(order, days_for_payment).deliver
    end
  end
end
 
comments powered by Disqus