diff --git a/lib/shopify_api/resources/fulfillment_order.rb b/lib/shopify_api/resources/fulfillment_order.rb index 501805068..3e6776fcf 100644 --- a/lib/shopify_api/resources/fulfillment_order.rb +++ b/lib/shopify_api/resources/fulfillment_order.rb @@ -16,5 +16,48 @@ def fulfillments(options = {}) fulfillment_hashes = get(:fulfillments, options) fulfillment_hashes.map { |fulfillment_hash| Fulfillment.new(fulfillment_hash) } end + + def move(new_location_id:) + body = { + fulfillment_order: { + new_location_id: new_location_id + } + } + keyed_fulfillment_orders = keyed_fulfillment_orders_from_response(post(:move, {}, body.to_json)) + load_keyed_fulfillment_order(keyed_fulfillment_orders, 'original_fulfillment_order') + keyed_fulfillment_orders + end + + def cancel + keyed_fulfillment_orders = keyed_fulfillment_orders_from_response(post(:cancel, {}, only_id)) + load_keyed_fulfillment_order(keyed_fulfillment_orders, 'fulfillment_order') + keyed_fulfillment_orders + end + + def close(message: nil) + body = { + fulfillment_order: { + message: message + } + } + load_attributes_from_response(post(:close, {}, body.to_json)) + end + + private + + def load_keyed_fulfillment_order(keyed_fulfillment_orders, key) + if keyed_fulfillment_orders[key]&.attributes + load(keyed_fulfillment_orders[key].attributes, false, true) + end + end + + def keyed_fulfillment_orders_from_response(response) + return load_attributes_from_response(response) if response.code != '200' + + keyed_fulfillment_orders = ActiveSupport::JSON.decode(response.body) + keyed_fulfillment_orders.transform_values do |fulfillment_order_attributes| + FulfillmentOrder.new(fulfillment_order_attributes) if fulfillment_order_attributes + end + end end end diff --git a/test/fulfillment_order_test.rb b/test/fulfillment_order_test.rb index 056f07c33..728137bb6 100644 --- a/test/fulfillment_order_test.rb +++ b/test/fulfillment_order_test.rb @@ -45,7 +45,6 @@ def setup context "#fulfillments" do should "be able to list fulfillments for a fulfillment order" do fulfillment_order = ShopifyAPI::FulfillmentOrder.find(519788021) - fake "fulfillment_orders/#{fulfillment_order.id}/fulfillments", method: :get, body: load_fixture('fulfillments') @@ -57,5 +56,91 @@ def setup assert_equal 450789469, fulfillment.order_id end end + + context "#move" do + should "move a fulfillment order to a new_location_id" do + fulfillment_order = ShopifyAPI::FulfillmentOrder.find(519788021) + new_location_id = 5 + + fake_original_fulfillment_order = fulfillment_order.clone + fake_original_fulfillment_order.status = 'closed' + fake_moved_fulfillment_order = ActiveSupport::JSON.decode(load_fixture('fulfillment_order')) + fake_moved_fulfillment_order['assigned_location_id'] = new_location_id + + request_body = { fulfillment_order: { new_location_id: 5 } } + body = { + original_fulfillment_order: fake_original_fulfillment_order, + moved_fulfillment_order: fake_moved_fulfillment_order, + remaining_fulfillment_order: nil, + } + fake "fulfillment_orders/519788021/move", :method => :post, + :request_body => ActiveSupport::JSON.encode(request_body), + :body => ActiveSupport::JSON.encode(body) + + response_fulfillment_orders = fulfillment_order.move(new_location_id: new_location_id) + + assert_equal 'closed', fulfillment_order.status + + assert_equal 3, response_fulfillment_orders.count + original_fulfillment_order = response_fulfillment_orders['original_fulfillment_order'] + refute_nil original_fulfillment_order + assert original_fulfillment_order.is_a?(ShopifyAPI::FulfillmentOrder) + assert_equal 'closed', original_fulfillment_order.status + + moved_fulfillment_order = response_fulfillment_orders['moved_fulfillment_order'] + refute_nil moved_fulfillment_order + assert moved_fulfillment_order.is_a?(ShopifyAPI::FulfillmentOrder) + assert_equal 'open', moved_fulfillment_order.status + assert_equal new_location_id, moved_fulfillment_order.assigned_location_id + + remaining_fulfillment_order = response_fulfillment_orders['remaining_fulfillment_order'] + assert_nil remaining_fulfillment_order + end + end + + context "#cancel" do + should "cancel a fulfillment order" do + fulfillment_order = ShopifyAPI::FulfillmentOrder.find(519788021) + assert_equal 'open', fulfillment_order.status + + cancelled = ActiveSupport::JSON.decode(load_fixture('fulfillment_order')) + cancelled['status'] = 'cancelled' + body = { + fulfillment_order: cancelled, + replacement_fulfillment_order: fulfillment_order, + } + fake "fulfillment_orders/519788021/cancel", :method => :post, :body => ActiveSupport::JSON.encode(body) + + response_fulfillment_orders = fulfillment_order.cancel + + assert_equal 'cancelled', fulfillment_order.status + assert_equal 2, response_fulfillment_orders.count + fulfillment_order = response_fulfillment_orders['fulfillment_order'] + assert_equal 'cancelled', fulfillment_order.status + replacement_fulfillment_order = response_fulfillment_orders['replacement_fulfillment_order'] + assert_equal 'open', replacement_fulfillment_order.status + end + end + + context "#close" do + should "be able to close fulfillment order" do + fulfillment_order = ShopifyAPI::FulfillmentOrder.find(519788021) + fulfillment_order.status = 'in_progress' + + closed = ActiveSupport::JSON.decode(load_fixture('fulfillment_order')) + closed['status'] = 'incomplete' + request_body = { + fulfillment_order: { + message: "Test close message." + } + } + fake "fulfillment_orders/519788021/close", :method => :post, + :request_body => ActiveSupport::JSON.encode(request_body), + :body => ActiveSupport::JSON.encode(closed) + + assert fulfillment_order.close(message: "Test close message.") + assert_equal 'incomplete', fulfillment_order.status + end + end end end diff --git a/test/test_helper.rb b/test/test_helper.rb index 4a3017c61..1bc275753 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -92,6 +92,7 @@ def assert_request_body(expected) end def fake(endpoint, options={}) + request_body = options.has_key?(:request_body) ? options.delete(:request_body) : nil body = options.has_key?(:body) ? options.delete(:body) : load_fixture(endpoint) format = options.delete(:format) || :json method = options.delete(:method) || :get @@ -104,7 +105,9 @@ def fake(endpoint, options={}) "https://this-is-my-test-shop.myshopify.com#{api_version.construct_api_path("#{endpoint}#{extension}")}" end - WebMock.stub_request(method, url).to_return( + stubbing = WebMock.stub_request(method, url) + stubbing = stubbing.with(body: request_body) if request_body + stubbing.to_return( body: body, status: status, headers: { content_type: "text/#{format}", content_length: 1 }.merge(options) ) end