Skip to content
This repository was archived by the owner on Sep 19, 2019. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,6 @@ gem 'mysql2'
gem 'sqlite3'
gem 'pg'

gem 'shipwire', github: 'nebulab/shipwire'

gemspec
59 changes: 59 additions & 0 deletions app/controllers/spree/shipwire/rate_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
module Spree
module Shipwire
class RateController < StoreController
respond_to :json

def create
rates = shipwire_rate(rate_params)

if rates.empty?
render json: { error: 'Rate not found' }, status: :not_found
elsif rates.map{ |r| r['serviceOptions'].any? }.none?
render json: { error: 'Service not found' }, status: :not_found
else
render json: { rates: rates }
end
rescue StandardError => e
render json: { error: e.message }, status: :internal_server_error
end

private

def shipwire_rate(rate_params)
rate = ::Shipwire::Rate.new.find(rate_params)
raise rate.error_report unless rate.ok?
rate.body['resource']['rates']
end

def rate_params
{
order: {
shipTo: order_shipwire_json[:shipTo],
items: order_shipwire_json[:items]
},
options: {
currency: order_shipwire_json[:options][:currency],
canSplit: order_shipwire_json[:options][:canSplit],
expectedShipDate: expected_ship_date
}
}
end

def expected_ship_date
ship_date = params[:expectedShipDate] || nil
return if ship_date.nil?

process_after_date = DateTime.strptime(ship_date).to_datetime.to_s
process_after_date if process_after_date > DateTime.current
end

def order
@order ||= current_order || Order.incomplete.find_by(guest_token: params[:order_guest_token])
end

def order_shipwire_json
@order_shipwire_json ||= order.to_shipwire
end
end
end
end
4 changes: 4 additions & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@
end
end

namespace :shipwire do
resources :rate, only: :create
end

namespace :shipwire_webhooks do
resources :stock, only: :create

Expand Down
99 changes: 99 additions & 0 deletions spec/controllers/spree/shipwire/rate_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
RSpec.describe Spree::Shipwire::RateController, type: :controller do
controller Spree::Shipwire::RateController do
end

let(:shipwire_product) { sw_product_factory.in_stock }
let(:product) { create(:product, sku: shipwire_product['sku']) }
let(:order) { create(:order_with_line_items, line_items_attributes: [product: variant.product] ) }

let(:variant) do
product.master.tap { |master| master.update_attributes(shipwire_id: shipwire_product['id']) }
end

let(:rate_params) { { order_guest_token: order.guest_token } }

subject { post :create, params: rate_params }

context 'when receive rate information', vcr: { cassette_name: 'shipwire/extract_rate' } do
let(:json_response) { JSON.parse(response.body) }
let(:service_options) { json_response['rates'].first }

it 'return service options info' do
subject

expect(json_response).to include 'rates'

expect(json_response['rates'].count).to eq 1
json_response['rates'].each do |service_options|
expect(service_options['serviceOptions'].count).to eq 3

service_options['serviceOptions'].each do |service_option|
expect(service_option).to include 'serviceLevelCode',
'serviceLevelName'

shipment = service_option['shipments'].first

expect(shipment).to include 'expectedDeliveryMaxDate',
'expectedDeliveryMinDate',
'expectedShipDate',
'warehouseName',
'carrier',
'cost'
end
end
end

context 'stub the rate api' do
before do
allow(Shipwire::Rate).to receive(:new).and_return shipwire_api
subject
end

context 'expected ship date' do
RSpec::Matchers.define :expected_ship_date do |expected_ship_date|
match { |hash| hash[:options][:expectedShipDate] == expected_ship_date }
end

let(:shipwire_api) { double('ShipwireApi', find: true) }

it 'is nil' do
expect(shipwire_api).to have_received(:find).with(expected_ship_date(nil))
end

context 'is in the future' do
let(:expectedShipDate) { (DateTime.current + 2.weeks).to_s }
let(:rate_params) do
{
order_guest_token: order.guest_token,
expectedShipDate: expectedShipDate
}
end

it 'expectedShipDate is setted' do
expect(shipwire_api).to have_received(:find).with(expected_ship_date(expectedShipDate))
end
end
end

context 'with empty services' do
context 'no service available' do
let(:shipwire_rate) do
{
resource: {
rates: [{ 'serviceOptions': [] }]
}
}.deep_stringify_keys
end

let(:shipwire_response) { double('ShipwireResponse', ok?: true, body: shipwire_rate ) }
let(:shipwire_api) { double('ShipwireApi', find: shipwire_response) }

it 'return not found' do
subject
expect(response).to have_http_status(:not_found)
end
end
end
end
end
end
Loading