From f4f6fb6a7a953d7fad5fc640b5d194dc977d0724 Mon Sep 17 00:00:00 2001 From: Rob Harrington Date: Thu, 9 Nov 2017 17:01:07 +1100 Subject: [PATCH] Update and process standing order payments prior to confirmation --- app/jobs/standing_order_confirm_job.rb | 8 ++ .../standing_order_payment_updater.rb | 19 +++++ spec/jobs/standing_order_confirm_job_spec.rb | 19 +++++ .../standing_order_payment_updater_spec.rb | 74 +++++++++++++++++++ 4 files changed, 120 insertions(+) create mode 100644 lib/open_food_network/standing_order_payment_updater.rb create mode 100644 spec/lib/open_food_network/standing_order_payment_updater_spec.rb diff --git a/app/jobs/standing_order_confirm_job.rb b/app/jobs/standing_order_confirm_job.rb index b17dc01dc4..eedd1d4a6f 100644 --- a/app/jobs/standing_order_confirm_job.rb +++ b/app/jobs/standing_order_confirm_job.rb @@ -1,3 +1,5 @@ +require 'open_food_network/standing_order_payment_updater' + class StandingOrderConfirmJob def perform ids = proxy_orders.pluck(:id) @@ -17,6 +19,8 @@ class StandingOrderConfirmJob end def process(order) + payment_updater.new(order).update! + order.process_payments! if order.payment_required? send_confirm_email(order) end @@ -27,4 +31,8 @@ class StandingOrderConfirmJob def recently_closed_order_cycles OrderCycle.closed.where('order_cycles.orders_close_at BETWEEN (?) AND (?) OR order_cycles.updated_at BETWEEN (?) AND (?)', 1.hour.ago, Time.now, 1.hour.ago, Time.now) end + + def payment_updater + OpenFoodNetwork::StandingOrderPaymentUpdater + end end diff --git a/lib/open_food_network/standing_order_payment_updater.rb b/lib/open_food_network/standing_order_payment_updater.rb new file mode 100644 index 0000000000..02f9f951a4 --- /dev/null +++ b/lib/open_food_network/standing_order_payment_updater.rb @@ -0,0 +1,19 @@ +module OpenFoodNetwork + class StandingOrderPaymentUpdater + + def initialize(order) + @order = order + end + + def update! + return unless payment + payment.update_attributes(amount: @order.outstanding_balance) + end + + private + + def payment + @payment ||= @order.pending_payments.last + end + end +end diff --git a/spec/jobs/standing_order_confirm_job_spec.rb b/spec/jobs/standing_order_confirm_job_spec.rb index f1d3894a53..b9800bfc39 100644 --- a/spec/jobs/standing_order_confirm_job_spec.rb +++ b/spec/jobs/standing_order_confirm_job_spec.rb @@ -118,5 +118,24 @@ describe StandingOrderConfirmJob do expect(job).to have_received(:send_confirm_email).with(order).once expect(ActionMailer::Base.deliveries.count).to be 1 end + + context "when payments need to be processed" do + let(:payment_updater_mock) { double(:payment_updater) } + let(:payment) { double(:payment, amount: 10) } + + before do + allow(order).to receive(:payment_total) { 0 } + allow(order).to receive(:total) { 10 } + allow(order).to receive(:pending_payments) { [payment] } + end + + it "updates the payment total and processes payments as required" do + expect(OpenFoodNetwork::StandingOrderPaymentUpdater).to receive(:new) { payment_updater_mock } + expect(payment_updater_mock).to receive(:update!) { true } + expect(payment).to receive(:process!) + expect(payment).to receive(:completed?) { true } + job.send(:process, order) + end + end end end diff --git a/spec/lib/open_food_network/standing_order_payment_updater_spec.rb b/spec/lib/open_food_network/standing_order_payment_updater_spec.rb new file mode 100644 index 0000000000..7bf9e17637 --- /dev/null +++ b/spec/lib/open_food_network/standing_order_payment_updater_spec.rb @@ -0,0 +1,74 @@ +require 'open_food_network/standing_order_payment_updater' + +module OpenFoodNetwork + describe StandingOrderPaymentUpdater do + let(:order) { create(:order) } + let(:updater) { OpenFoodNetwork::StandingOrderPaymentUpdater.new(order) } + + describe "#payment" do + context "when only one payment exists on the order" do + let!(:payment) { create(:payment, order: order) } + + context "where the payment is in the 'checkout' state" do + it { expect(updater.send(:payment)).to eq payment } + end + + context "where the payment is in some other state" do + before { payment.update_attribute(:state, 'pending') } + it { expect(updater.send(:payment)).to be nil } + end + end + + context "when more that one payment exists on the order" do + let!(:payment1) { create(:payment, order: order) } + let!(:payment2) { create(:payment, order: order) } + + context "where more than one payment is in the 'checkout' state" do + it { expect(updater.send(:payment)).to eq payment1 } + end + + context "where only one payment is in the 'checkout' state" do + before { payment1.update_attribute(:state, 'pending') } + it { expect(updater.send(:payment)).to eq payment2 } + end + + context "where no payments are in the 'checkout' state" do + before do + payment1.update_attribute(:state, 'pending') + payment2.update_attribute(:state, 'pending') + end + + it { expect(updater.send(:payment)).to be nil } + end + end + end + + describe "#update!" do + let!(:payment){ create(:payment, amount: 10) } + + context "when no payment is present" do + before { allow(updater).to receive(:payment) { nil } } + it { expect(updater.update!).to be nil } + end + + context "when a payment is present" do + before { allow(updater).to receive(:payment) { payment } } + + context "when the payment total doesn't match the outstanding balance on the order" do + before { allow(order).to receive(:outstanding_balance) { 5 } } + it "updates the payment total to reflect the outstanding balance" do + expect{updater.update!}.to change(payment, :amount).from(10).to(5) + end + end + + context "when the payment total matches the outstanding balance on the order" do + before { allow(order).to receive(:outstanding_balance) { 10 } } + + it "does nothing" do + expect{updater.update!}.to_not change(payment, :amount).from(10) + end + end + end + end + end +end