-
Notifications
You must be signed in to change notification settings - Fork 474
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add validation and tests for deprecation of product and variant inventory-related fields #655
Conversation
b178725
to
14a697c
Compare
lib/shopify_api/resources/product.rb
Outdated
@@ -16,6 +16,15 @@ def price_range | |||
end | |||
end | |||
|
|||
def serializable_hash(options = {}) | |||
super.except("total_inventory") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm confused why this is needed? For versions without the field, it won't be here anyway. And for versions with it, this is a breaking change since it's done unconditionally.
If someone were still on 2019-07 for example, this would be a breaking change.
Same question applies for the variant change below.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, I see what you mean. Honestly, I can't remember why we added that (it was before Christmas) but looking at it now and based on your arguments above I agree that we can remove it. 👍
@eljojo Do you remember the logic behind the changes in serializable_hash
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think in these scenarios we can actually strip them out from serializable_hash
in versions 2019-10
and later; if we already know we're going to fail those requests without clients making those changes, we should at least make it easier for them by omitting them in the scenario where they copy the response directly into the request.
lib/shopify_api/resources/product.rb
Outdated
@@ -16,6 +16,11 @@ def price_range | |||
end | |||
end | |||
|
|||
def total_inventory=(new_value) | |||
raise(ShopifyAPI::ValidationException, 'deprecated behaviour') unless Base.api_version < ApiVersion.find_version('2019-10') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe the exception messages should point to https://help.shopify.com/en/api/guides/inventory-migration-guide?
603f717
to
cea7bb1
Compare
Are they going to merge this, issue still exists? |
Thanks for the ping! We're still working out a few things with the deprecation and we'll update this PR once it is sorted. Stay tuned... |
Hello - do we have an ETA on this being merged? As of now, any shopify product / variant edit / create / deletes are broken right now. I'm on standby waiting on this fix. |
I'm doing the following temp fix (#632 (comment)) on my side before this is merged:
|
We had to do an urgent workaround. |
I'm working on updating the current PR to remove those fields from the response for requests using the Oct 2019 API release and later. |
This change just moves the error to the gem, rather than relying on the response from Shopify, is that correct? Or have I misunderstood? |
Yes, that's correct |
cea7bb1
to
0ed662d
Compare
…in 2019-10 and later
82843fa
to
4235a6f
Compare
To be clear this PR makes 2 changes if a client is using the 2019-10 API version or later: The deprecations are outlined here: @swalkinshaw Would appreciate your feedback again on this one to make sure we're aligned now that the changes have been shipped to Core. |
Hi, when will this be merged? |
HI, PUT https://chriscoffee-dev.myshopify.com/admin/api/2019-10/products/4340483522611.json {"product":{"id":4340483522611,"title":"1.0mm #0 Steam Tip","body_html":"\u003cp\u003e8.8mm female thread\u003c/p\u003e","vendor":"Slayer Espresso","product_type":"Slayer","created_at":"2019-11-10T21:17:26-05:00","handle":"1-0mm-0-steam-tip","updated_at":"2020-02-17T00:15:03-05:00","published_at":"2019-11-10T21:17:25-05:00","template_suffix":null,"published_scope":"web","tags":"Accessories","admin_graphql_api_id":"gid://shopify/Product/4340483522611","variants":[{"id":31148589187123,"product_id":4340483522611,"title":"Default Title","price":"25.95","sku":"46000-50340","position":1,"inventory_policy":"deny","compare_at_price":null,"fulfillment_service":"manual","inventory_management":"shopify","option1":"Default Title","option2":null,"option3":null,"created_at":"2019-11-10T21:17:26-05:00","updated_at":"2020-02-11T14:02:55-05:00","taxable":true,"barcode":"false","grams":23,"image_id":null,"weight":0.0507,"weight_unit":"lb","inventory_item_id":32667358199859,"inventory_quantity":49,"old_inventory_quantity":49,"tax_code":"","requires_shipping":true,"admin_graphql_api_id":"gid://shopify/ProductVariant/31148589187123"}],"options":[{"id":5642415570995,"product_id":4340483522611,"name":"Title","position":1,"values":["Default Title"]}],"images":[{"id":13402636582963,"product_id":4340483522611,"position":1,"created_at":"2019-11-10T21:17:26-05:00","updated_at":"2019-11-10T21:17:26-05:00","alt":null,"width":1200,"height":1200,"src":"https://cdn.shopify.com/s/files/1/0251/6398/9043/products/46000-50340.jpg?v=1573438646","variant_ids":[],"admin_graphql_api_id":"gid://shopify/ProductImage/13402636582963"}],"image":{"id":13402636582963,"product_id":4340483522611,"position":1,"created_at":"2019-11-10T21:17:26-05:00","updated_at":"2019-11-10T21:17:26-05:00","alt":null,"width":1200,"height":1200,"src":"https://cdn.shopify.com/s/files/1/0251/6398/9043/products/46000-50340.jpg?v=1573438646","variant_ids":[],"admin_graphql_api_id":"gid://shopify/ProductImage/13402636582963"}}} Response:BadRequest: Response(code=400, body="{"error":"Write requests to inventory_quantity and inventory_quantity_adjustment are no longer supported. Please use the Inventory Levels API."}", headers={'x-shopify-stage': 'production', 'x-stats-userid': '', 'cf-cache-status': 'DYNAMIC', 'x-shopify-shop-api-call-limit': '1/80', 'x-shopid': '25163989043', 'http_x_shopify_shop_api_call_limit': '1/80', 'x-request-id': 'e3878b1e-6905-4bab-9a43-139e44cce883', 'x-xss-protection': '1; mode=block; report=/xss-report?source%5Baction%5D=update&source%5Bapp%5D=Shopify&source%5Bcontroller%5D=admin%2Fproducts&source%5Bsection%5D=admin_api&source%5Buuid%5D=e3878b1e-6905-4bab-9a43-139e44cce883', 'x-content-type-options': 'nosniff', 'x-stats-apiclientid': '3250443', 'x-shardid': '50', 'transfer-encoding': 'chunked', 'referrer-policy': 'origin-when-cross-origin', 'x-sorting-hat-shopid': '25163989043', 'x-download-options': 'noopen', 'x-stats-apipermissionid': '198562512947', 'set-cookie': '__cfduid=d3f64e40387b1a49f6442ae64e2cb1e2f1584723654; expires=Sun, 19-Apr-20 17:00:54 GMT; path=/; domain=.myshopify.com; HttpOnly; SameSite=Lax', 'x-shopify-api-terms': 'By accessing or using the Shopify API you agree to the Shopify API License and Terms of Use at https://www.shopify.com/legal/api-terms', 'x-shopify-api-version': '2019-10', 'date': 'Fri, 20 Mar 2020 17:00:55 GMT', 'cf-ray': '5770fdfb4900eff5-EWR', 'expect-ct': 'max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"', 'alt-svc': 'h3-27=":443"; ma=86400, h3-25=":443"; ma=86400, h3-24=":443"; ma=86400, h3-23=":443"; ma=86400', 'content-security-policy': "default-src 'self' data: blob: 'unsafe-inline' 'unsafe-eval' https://* shopify-pos://; block-all-mixed-content; child-src 'self' https:// shopify-pos://; connect-src 'self' wss:// https://*; frame-ancestors 'none'; img-src 'self' data: blob: https:; script-src https://cdn.shopify.com https://cdn.shopify.cn https://checkout.shopifycs.com https://js-agent.newrelic.com https://bam.nr-data.net https://api.stripe.com https://mpsnare.iesnare.com https://appcenter.intuit.com https://www.paypal.com https://js.braintreegateway.com https://c.paypal.com https://maps.googleapis.com https://www.google-analytics.com https://v.shopify.com https://widget.intercom.io https://js.intercomcdn.com 'self' 'unsafe-inline' 'unsafe-eval'; upgrade-insecure-requests; report-uri /csp-report?source%5Baction%5D=update&source%5Bapp%5D=Shopify&source%5Bcontroller%5D=admin%2Fproducts&source%5Bsection%5D=admin_api&source%5Buuid%5D=e3878b1e-6905-4bab-9a43-139e44cce883", 'x-dc': 'gcp-us-central1,gcp-us-east1,gcp-us-east1', 'strict-transport-security': 'max-age=7889238', 'x-sorting-hat-podid': '50', 'server': 'cloudflare', 'connection': 'close', 'x-permitted-cross-domain-policies': 'none', 'x-frame-options': 'DENY', 'content-type': 'application/json; charset=utf-8'}, msg="Bad Request") |
The deprecated parameters are still being sent in the request you pasted above: "inventory_quantity": 49,
"old_inventory_quantity": 49, |
Correct, I thought the update would remove or ignore them, I GET for same same product, these fields are included. I thought the point of the update was to fix the Bad Request issue. So I still have to strip them out? |
I am not setting inventory 1., and 2. states the fields would be removed ? |
Do you have some sample code for what you're doing? Also, which API version are you using? |
I set the version 2019-10, as base url. I am just trying to unpublish a product from our ERP. Here is the code, it was working until Mach 16.
|
The real issue I have is I did refactor code for 2019-10, months ago, what changes occured on the March 16th, that broke this. I have many functions that I would have to update, we update stock using the correct method without issue. I feeling is the GET is pulling all fields, fine. But if I tried to set inventory the old way, then yes I should get a bad request, not when I am updating two fields. So if I change the 'title' it is going to throw the same Bad Request. These fields should be ignored by the server since they are not used. |
This is the code we pass to update inventory, the fields,
|
Same issue as here:#702 |
We're going to revert the changes introduced by this PR and work on a new fix for the issue. |
end | ||
|
||
def serializable_hash(options = {}) | ||
allow_inventory_params? ? super(options) : super(options).except('inventory_quantity', 'old_inventory_quantity') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changing to
def serializable_hash(options = {})
allow_inventory_params? ? super(options) : super(options).tap do |s|
(s['variant'] || s).except!('inventory_quantity', 'old_inventory_quantity')
end
end
Fixes this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
end | ||
|
||
def serializable_hash(options = {}) | ||
allow_inventory_params? ? super(options) : super(options).except('inventory_quantity', 'old_inventory_quantity') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this accurate? Those fields were deprecated for writes, but reading variant.total_inventory
should still be supported
fixes #632
The following fields on Product (
total_inventory
) and Variant (inventory_quantity_adjustment
,inventory_quantity
,old_inventory_quantity
) were deprecated earlier this year and were removed in the 2019-10 api version.This PR updates the code and adds tests to ensure the behaviour is correct.
Reviewer's note: In
test/test_helper.rb
I changed the code to return the current API version if none was specified. The old code returned the Jan 2019 version. I believe this new behaviour is correct but would like confirmation.