Skip to content

Commit

Permalink
Merge pull request #54 from mejuri-inc/develop
Browse files Browse the repository at this point in the history
Preparing the new v0.0.10 release
  • Loading branch information
sebastiandl authored Aug 4, 2021
2 parents 57abedf + 3fd9921 commit 10152ca
Show file tree
Hide file tree
Showing 6 changed files with 163 additions and 91 deletions.
17 changes: 13 additions & 4 deletions app/services/flowcommerce_spree/webhooks/capture_upserted_v2.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,25 @@ def process
errors << { message: 'Order number param missing' } && (return self) unless order_number

if (order = Spree::Order.find_by(number: order_number))
upsert_order_captures(order, capture)
payments = order.flow_io_payments
map_payment_captures_to_spree(order, payments) if payments.present?
order
if order.payments.any?
store_payment_capture(order, capture)
else
FlowcommerceSpree::UpdatePaymentCaptureWorker.perform_in(1.minute, order.number, capture)
order
end
else
errors << { message: "Order #{order_number} not found" }
self
end
end

def store_payment_capture(order, capture)
upsert_order_captures(order, capture)
payments = order.flow_io_payments
map_payment_captures_to_spree(order, payments) if payments.present?
order
end

private

def upsert_order_captures(order, capture)
Expand Down
16 changes: 16 additions & 0 deletions app/workers/flowcommerce_spree/flow_io_worker.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# frozen_string_literal: true

module FlowcommerceSpree
class FlowIoWorker
include Sidekiq::Worker

sidekiq_retries_exhausted do |message, exception|
Rails.logger.warn("[!] #{self.class} max attempts reached: #{message} - #{exception}")
notification_setting = FlowcommerceSpree::Config.notification_setting
return unless notification_setting[:slack].present?

slack_message = "[#{Rails.env}] #{message}"
Slack_client.chat_postMessage(channel: notification_setting[:slack][:channel], text: slack_message)
end
end
end
12 changes: 1 addition & 11 deletions app/workers/flowcommerce_spree/import_item_worker.rb
Original file line number Diff line number Diff line change
@@ -1,19 +1,9 @@
# frozen_string_literal: true

module FlowcommerceSpree
class ImportItemWorker
include Sidekiq::Worker
class ImportItemWorker < FlowIoWorker
sidekiq_options retry: 3, queue: :flow_io

sidekiq_retries_exhausted do |message, exception|
Rails.logger.warn("[!] FlowcommerceSpree::ImportItemWorker max attempts reached: #{message} - #{exception}")
notification_setting = FlowcommerceSpree::Config.notification_setting
return unless notification_setting[:slack].present?

slack_message = "[#{Rails.env}] #{message}"
Slack_client.chat_postMessage(channel: notification_setting[:slack][:channel], text: slack_message)
end

def perform(variant_sku)
variant = Spree::Variant.find_by sku: variant_sku
return unless variant
Expand Down
15 changes: 15 additions & 0 deletions app/workers/flowcommerce_spree/update_payment_capture_worker.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# frozen_string_literal: true

module FlowcommerceSpree
class UpdatePaymentCaptureWorker < FlowIoWorker
sidekiq_options retry: 3, queue: :flow_io

def perform(order_number, capture = {})
order = Spree::Order.find_by number: order_number
raise 'Order has no payments' if order.payments.empty?

FlowcommerceSpree::Webhooks::CaptureUpsertedV2.new({ capture: capture }.as_json)
.store_payment_capture(order, capture)
end
end
end
167 changes: 91 additions & 76 deletions spec/services/flowcommerce_spree/webhooks/capture_upserted_v2_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -121,130 +121,145 @@
expect(instance).to receive(:upsert_order_captures).with(order, data['capture'])
end

context 'and the order contains no flow_io payments' do
it 'returns the Spree::Order with upserted captures, not mapping captures to Spree' do
expect(instance).not_to receive(:map_payment_captures_to_spree)
context 'when order has a payment assocaited' do
let!(:payment) { create(:payment, order: order, payment_method_id: gateway.id) }

result = instance.process
context 'and the order contains no flow_io payments' do
it 'returns the Spree::Order with upserted captures, not mapping captures to Spree' do
expect(instance).not_to receive(:map_payment_captures_to_spree)

expect_order_with_capture(result, 'succeeded')
result = instance.process

expect_order_with_capture(result, 'succeeded')
end
end
end

context 'and the order contains flow_io payments' do
let(:flow_payment) { build(:flow_order_payment, reference: order_auth.id) }
let(:zone) { create(:germany_zone, :with_flow_data) }
context 'and the order contains flow_io payments' do
let(:flow_payment) { build(:flow_order_payment, reference: order_auth.id) }
let(:zone) { create(:germany_zone, :with_flow_data) }
let(:payment_amount) { capture.amount }

[Time.now.utc, nil].each do |timestamp|
context "and the order is #{timestamp ? 'completed' : 'not_completed'}" do
let(:order) { create(:order, zone: zone, completed_at: timestamp) }
let(:finalize) { timestamp ? false : true }
[Time.now.utc, nil].each do |timestamp|
context "and the order is #{timestamp ? 'completed' : 'not_completed'}" do
let(:order) { create(:order, zone: zone, completed_at: timestamp) }
let(:finalize) { timestamp ? false : true }

before do
order.flow_data['order']['payments'] = [flow_payment]
order.update_column(:meta, order.meta.to_json)
before do
order.flow_data['order']['payments'] = [flow_payment]
order.update_column(:meta, order.meta.to_json)

expect(instance).to receive(:map_payment_captures_to_spree)
end
expect(instance).to receive(:map_payment_captures_to_spree)
end

context 'and received capture is successful' do
context 'and capture authorization matches flow_io payment authorization' do
context 'and a Spree::Payment with received capture authorization exists' do
let(:payment_amount) { capture.amount }
let!(:payment) do
create(:payment,
payment_method_id: gateway.id, amount: payment_amount, response_code: order_auth.id)
end
context 'and received capture is successful' do
context 'and capture authorization matches flow_io payment authorization' do
context 'and a Spree::Payment with received capture authorization exists' do
let(:payment_amount) { capture.amount }
let!(:payment) do
create(:payment,
order: order,
payment_method_id: gateway.id,
amount: payment_amount,
response_code: order_auth.id)
end

context 'and no Spree::PaymentCaptureEvent exists for this payment' do
before { Spree::PaymentCaptureEvent.destroy_all }
context 'and no Spree::PaymentCaptureEvent exists for this payment' do
before { Spree::PaymentCaptureEvent.destroy_all }

context 'and payment state is not complete' do
context 'and payment amount is not bigger than capture amount' do
it 'creates PaymentCaptureEvent, completes payment, returns order with upserted captures' do
expect(instance).to receive(:captured_payment)
expect_any_instance_of(Spree::Payment).to receive(:complete)
expect_order_finalize(order_finalize: finalize)
context 'and payment state is not complete' do
context 'and payment amount is not bigger than capture amount' do
it 'creates PaymentCaptureEvent, completes payment, returns order with upserted captures' do
expect(instance).to receive(:captured_payment)
expect_any_instance_of(Spree::Payment).to receive(:complete)
expect_order_finalize(order_finalize: finalize)

result = nil
expect { result = instance.process }
.to change { Spree::PaymentCaptureEvent.count }.from(0).to(1)
result = nil
expect { result = instance.process }
.to change { Spree::PaymentCaptureEvent.count }.from(0).to(1)

created_capture_event = Spree::PaymentCaptureEvent.first
created_capture_event = Spree::PaymentCaptureEvent.first

expect(created_capture_event.amount).to eql(capture.amount)
expect(created_capture_event.flow_data['id']).to eql(capture.id)
expect(payment.reload.state).to eql('completed')
expect_order_with_capture(result, 'succeeded')
expect(created_capture_event.amount).to eql(capture.amount)
expect(created_capture_event.flow_data['id']).to eql(capture.id)
expect(payment.reload.state).to eql('completed')
expect_order_with_capture(result, 'succeeded')
end
end
end

context 'and payment amount is bigger than capture amount' do
let(:payment_amount) { capture.amount + 1 }
context 'and payment amount is bigger than capture amount' do
let(:payment_amount) { capture.amount + 1 }

it 'creates a PaymentCaptureEvent, and returns order with upserted captures' do
expect(instance).to receive(:captured_payment)
expect_any_instance_of(Spree::Payment).not_to receive(:complete)
expect(FlowcommerceSpree::OrderUpdater).not_to receive(:new)
expect_any_instance_of(FlowcommerceSpree::OrderUpdater).not_to receive(:finalize_order)
it 'creates a PaymentCaptureEvent, and returns order with upserted captures' do
expect(instance).to receive(:captured_payment)
expect_any_instance_of(Spree::Payment).not_to receive(:complete)
expect(FlowcommerceSpree::OrderUpdater).not_to receive(:new)
expect_any_instance_of(FlowcommerceSpree::OrderUpdater).not_to receive(:finalize_order)

result = nil
expect { result = instance.process }
.to change { Spree::PaymentCaptureEvent.count }.from(0).to(1)
result = nil
expect { result = instance.process }
.to change { Spree::PaymentCaptureEvent.count }.from(0).to(1)

created_capture_event = Spree::PaymentCaptureEvent.first
created_capture_event = Spree::PaymentCaptureEvent.first

expect(created_capture_event.amount).to eql(capture.amount)
expect(created_capture_event.flow_data['id']).to eql(capture.id)
expect(payment.reload.state).to eql('checkout')
expect_order_with_capture(result, 'succeeded')
expect(created_capture_event.amount).to eql(capture.amount)
expect(created_capture_event.flow_data['id']).to eql(capture.id)
expect(payment.reload.state).to eql('checkout')
expect_order_with_capture(result, 'succeeded')
end
end
end
end
end

context 'and a Spree::PaymentCaptureEvent for this payment already exists' do
let!(:capture_event) do
create(:payment_capture_event, payment_id: payment.id, flow_data: { id: capture.id })
context 'and a Spree::PaymentCaptureEvent for this payment already exists' do
let!(:capture_event) do
create(:payment_capture_event, payment_id: payment.id, flow_data: { id: capture.id })
end

it 'returns the Spree::Order with upserted captures, not creating a Spree::PaymentCaptureEvent' do
result = expect_no_new_capture_events(order_finalize: finalize)
expect_order_with_capture(result, 'succeeded')
end
end
end

context 'and no Spree::Payment with received capture authorization exists' do
it 'returns the Spree::Order with upserted captures, not creating a Spree::PaymentCaptureEvent' do
result = expect_no_new_capture_events(order_finalize: finalize)
expect_order_with_capture(result, 'succeeded')
end
end
end

context 'and no Spree::Payment with received capture authorization exists' do
context 'and capture authorization does not match flow_io payment authorization' do
let(:flow_payment) { build(:flow_order_payment, reference: 'wrong auth') }

it 'returns the Spree::Order with upserted captures, not creating a Spree::PaymentCaptureEvent' do
result = expect_no_new_capture_events(order_finalize: finalize)
expect_order_with_capture(result, 'succeeded')
end
end
end

context 'and capture authorization does not match flow_io payment authorization' do
let(:flow_payment) { build(:flow_order_payment, reference: 'wrong auth') }
context 'and received capture is not successful' do
let(:data) { { 'capture' => Oj.load(failed_capture.to_json) } }

it 'returns the Spree::Order with upserted captures, not creating a Spree::PaymentCaptureEvent' do
it 'returns the Spree::Order with upserted captures' do
result = expect_no_new_capture_events(order_finalize: finalize)
expect_order_with_capture(result, 'succeeded')
expect_order_with_capture(result, 'failed')
end
end
end

context 'and received capture is not successful' do
let(:data) { { 'capture' => Oj.load(failed_capture.to_json) } }

it 'returns the Spree::Order with upserted captures' do
result = expect_no_new_capture_events(order_finalize: finalize)
expect_order_with_capture(result, 'failed')
end
end
end
end
end
end

context 'when order has no payments assocaited' do
it 'delays order capture' do
instance.process
expect(FlowcommerceSpree::UpdatePaymentCaptureWorker).to have_enqueued_sidekiq_job(order.number, anything)
end
end
end
end
end
Expand Down
27 changes: 27 additions & 0 deletions spec/workers/update_payment_capture_worker_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# frozen_string_literal: true

require 'rails_helper'

RSpec.describe FlowcommerceSpree::UpdatePaymentCaptureWorker, type: :worker do
let(:gateway) { create(:flow_io_gateway) }
let(:order) { create(:order) }
subject(:job) { described_class.new }

describe '#perform' do
context 'when order has payments' do
let!(:payment) { create(:payment, order: order, payment_method_id: gateway.id) }

it 'calls CaptureUpsertedV2#store_payment_capture method' do
expect_any_instance_of(FlowcommerceSpree::Webhooks::CaptureUpsertedV2).to(receive(:store_payment_capture))
job.perform(order.number, anything)
end
end

context 'when order has no payments' do
it 'does not call CaptureUpsertedV2#store_payment_capture method' do
expect_any_instance_of(FlowcommerceSpree::Webhooks::CaptureUpsertedV2).not_to(receive(:store_payment_capture))
expect { job.perform(order.number, anything) }.to raise_error 'Order has no payments'
end
end
end
end

0 comments on commit 10152ca

Please sign in to comment.