Shopify cart/update.js endpoint not updating the correct lineitem - shopify

There are several items in the cart with the same variant id, but different properties and discounts. I noticed that when I make a post request using the lineitem keys to the cart/update.js endpoint, it is not updating the correct line item. It's just updating the first item that has the variant id..
Any reason why this could happen?
For example, there are multiple lineitems with the variant id "40072319336547".
When I run this
jQuery.post(window.Shopify.routes.root + 'cart/update.js', "updates[40072319336547:62a477719b1f798b23f1ce16199c1668]=3" );
It's not updating the line item with key "40072319336547:62a477719b1f798b23f1ce16199c1668". Just some other lineitem with the variant id 40072319336547.

In that case (multiple lines with same variant id in the cart) is better to use change.js instead of update.js: https://shopify.dev/api/ajax/reference/cart#post-locale-cart-change-js
I'm doing like this:
$.ajax({
type: "post", url: "/cart/change.js", data: [
{"quantity": 2, "line": 0},
{"quantity": 4, "line": 1},
], dataType: 'json'
});
You see that I don't use the variantId but I'm using the line index. The downside of this approach is that if you need to apply a change to all the same variant ids you need to know which lines have to be changed. But that can be done reading the respone from cart.js

Related

How to iterate over a dynamic array of objects and use each object as a parameter in test?

I started my adventure with Karate a month ago. I have a simple GET test called getAllCars.feature showing a list of cars currently available:
[
{
"brandName": "BMW",
"id": 1,
"winterTires": false,
"modelName": "X5"
},
{
"brandName": "Opel",
"id": 34,
"winterTires": true,
"modelName": "Insignia"
},
{
"brandName": "Mercedes-Benz",
"id": 36,
"winterTires": true,
"modelName": "GLE Coupe"
},
{
"brandName": "Huydai",
"id": 251,
"winterTires": false,
"modelName": "i30"
}
]
I have to use each id as a parameter for the next feature file, the problem is, the list of cars is dynamic, ids don't repeat and I will have to use this list of ids for several other feature files. I managed to create a helper getCarIds.feature, which creates an array of objects "carId": "#number":
Feature: Get car IDs
Scenario: Get car IDs
* call read('classpath:x/automation/cars/getAllCars.feature')
* def carIds = $response[*].id
* def carFeeder = karate.mapWithKey(carIds, 'carId')
The following getCarParameters.feature has to iterate over the array from getCarIds.feature and pass each id as a parameter to get a response with performance parameters of each car and I don't know how to use each id separately as a parameter (keeping in mind that the list of ids is changing):
Feature: Get parameters of each car
Scenario: Get parameters for each car
* call read('classpath:x/automation/cars/getCarIds.feature')
Given url carUrl + '/carparameters'
And param carId =
When method GET
Then status 200
I managed to do it when passing the values from getCarIds.feature to getCarParameters.feature like described here by adding following line to getCarIds.feature:
* call read('classpath:x/automation/cars/getCarParameters.feature') carFeeder
but several other tests require car ids. I need getCarIds.feature to be reusable, so I would have to retrieve data from feature file, which creates the array with ids, instead of passing it to the GET feature and apparently it isn't so easy. Maybe my approach is completely wrong.
I think this is a valid case for karate.callSingle(): https://github.com/karatelabs/karate#karatecallsingle
So you can actually stick this in any feature and it is guaranteed to execute only once across your test suite. If the data is indeed something used by a majority of your test suite, you could even do this initialization in karate-config.js.
So this should work. First the reusable feature common.feature. Instead of the hard-coded response, you know how to make an actual HTTP request.
#ignore
Feature:
Scenario:
* def response =
"""
[
{
"brandName": "BMW",
"id": 1,
"winterTires": false,
"modelName": "X5"
},
{
"brandName": "Opel",
"id": 34,
"winterTires": true,
"modelName": "Insignia"
}
]
"""
* print 'getting car ids'
* def carIds = response.map(x => ({ id: x.id }))
Note the use of the JS map() function above, which I have started to recommend instead of JsonPath.
And here is a feature that uses the above. This uses the new #setup annotation that makes it easy to "loop": https://github.com/karatelabs/karate#setup
You can try this example quickly, and watch it make 2 requests using a param id from the loop.
Feature:
#setup
Scenario:
* def data = karate.callSingle('call-single-common.feature').carIds
Scenario Outline:
* url 'https://httpbin.org/get'
* param id = id
* method get
Examples:
| karate.setup().data |
There are other ways to loop, refer: https://github.com/karatelabs/karate#data-driven-features

Create Shopify product with Variant SKU using API

I am trying to create Products on Shopify using the API,
In the CSV upload there is a field Variant SKU which sets the (default) product SKU, I can't seem to find the correct way to create a product along with this value?
I tried (python3);
import requests
import json
from config import SHOPIFY_URL
payload = {
'product': {
'title': 'Hello Product',
'variants': {
'option1': 'Primary',
'sku': 'hello-product'
}
}
}
requests.post(
f'{SHOPIFY_URL}/products.json',
headers = {'content-type': 'application/json'},
data=json.dumps(payload)
)
The product get created but the SKU doesn't.
The TL;DR of my question;
What to I need to pass to fill the Product CSV Upload file's field Variant SKU?
Update
Thanks to David Lazar's comments, I realized that I need to use a list of variants.
payload = {
'product': {
'title': 'Hello Product',
'variants': [
{
'option1': 'Primary',
'sku': 'hello-product'
}
]
}
}
This however creates the product with one variant using the passed SKU.However what I am looking is to create the Porduct with its own SKU, no variations for the product, just a SKU for the product.

How to add modifiers to cart line item in BigCommerce Api

I already tried the solution given in this Cart API V3: Can't create a Cart for product that has options link but it's not working for me.
modifier is extra fitting added to the product like "name tag" for suitcase.
I tried to add the modifier in "option_selections" like below but it returns 422 error.
Request:
{
"quantity":"1",
"product_id":"5846",
"variant_id":150922,
"list_price":" 170.00",
"option_selections":[{"option_id":23800, "option_value":"10088"}]
}
Response:
StatusCode: 422, ReasonPhrase: 'Unprocessable Entity'
Thanks for your reply in advance.
If you're creating a new cart, try this request body (POST to /carts endpoint):
{
"line_items": [
{
"quantity": 1,
"product_id": 76,
"list_price": 170.00,
"option_selections": [
{
"option_id": 21506,
"option_value": 10090
}
]
}
]
}
You shouldn't have quotes around any of these field values--list_price, product_id, etc all accept a number, not a string.
If you want to add a new line item to an existing cart, you can use the same request body as above. The request will be a POST to carts/{cartID}/items
EDIT:
If you are updating a line item that already exists in the cart, you'll want to make a PUT to /carts/{cartID}/items/{itemID}.
Request body:
{
"line_item": {
"quantity": 1,
"product_id": 76,
"list_price": 170.00,
"option_selections": [
{
"option_id": 21506,
"option_value": 10090
}
]
}
}
Note: it does need to be "line_item" rather than "line_items" when updating a single cart item. I'll work with our documentation team to get this updated in the API reference.
I was able to solve the issue, though I agree with Karen White's answer, I wanted to add a product which has options like colors and modifiers too. Which I was not able to achieve with that. I used the following data to add product with option and modifier.
Instead of passing variant_id, pass variant as option (option_id gets option's id and option_value gets option value's id) and pass modifier as option (modifier option_id gets option's id and option_value gets option value's id)
{
"line_items": [{
"quantity": 1,
"product_id": 5846,
"option_selections": [{
"option_id": 23799,
"option_value": 10173
}, {
"option_id": 23800,
"option_value": 10088
}]
}]
}

OnDemandGrid (Dgrid) won't fire a request

When scrolling the grid, it does not fire a new request for more items when you reach the end of the 20 items
I am using Dojo version 1.10.4. I created a TrackableRest Store
var TrackableRest = declare([Rest, Trackable]);
var interceptStore = new TrackableRest({
target: 'rest/intercepts/',
accepts: "application/json",
sortParam: 'sort',
rangeStartParam: 'offset',
rangeCountParam: 'limit',
headers:{
'Accept': "application/json",
'Content-Type':"application/json",
'charset':"UTF-8"
},
idProperty: 'id'
});
Then I created a grid:
var grid = window.grid = new CustomGrid({
id: 'grid',
//sort: [{property:'ELNOT'},{property:'RF_AVG'}], // Initialize sort on last name, ascending
collection: interceptsStore,
sort: "id",
getBeforePut: false,
columns: getColumns(),
allowSelectAll: true,
loadingMessage: 'Loading data...',
noDataMessage: 'No results found.',
title: "All",
minRowsPerPage: 20,
maxRowsPerPage: 250
});
The request is sent
http://localhost:8080/OlympiaMap/rest/intercepts/?sort=+id&offset=0&limit=20
And the response includes the header Content-Range with a value of items=0-20/606
and the data looks like
enter image description here
So after two days of waiting I realized that even though you return the Content Header in the desired format it appears that it is using the values in your response total, limit and offset (or whatever you choose for your start and count params). For instance, in my response headers I returned Content-Range with a value of "items 0-20/606" but in the actual response I have a items array with 20 items and a total of 20. When I hard coded this valued (just to test) to match the 606 value I started to see the virtual scrolling work and send request incrementing the start and count. Like this
1st on page load
http://localhost:8080/OlympiaMap/rest/intercepts/?sort=+id&offset=0&limit=20
While scrolling
http://localhost:8080/OlympiaMap/rest/intercepts/?sort=+id&offset=20&limit=20
etc and so on
This is due to a lack of documentation on part of the dstore and dgrid

Querying (and filtering) in a many-to-many relationship in Backand

I'm trying to use the pet-owner example to create some sort of playlist app where a playlist can be shared among different users.
I have read both links to understand how many-to-many relationship is created in Backand:
Link 1 -
Link 2
According to pet's example, to get all owners from one pet I should get the pet object (using its id field) and then filter its user_pets list matching the user id. That may work for small amount of users/pets but I'd rather prefer to query user_pets table directly by filtering by user_id and pet_id.
My approach has been this code without success:
$http({
method: 'GET',
url: getUrl(), // this maps to pets_owner "table"
params: {
deep: true,
exclude: 'metadata',
filter: [
{ fieldName: 'pet', operator: 'equals', value: pet_id },
{ fieldName: 'owner', operator: 'equals', value: user_id }
]
}
})
Any idea how to query/filter to get only related results?
Thanks in advance
Because user_id and pet_d are both object fields the operator should be "in"
From Backand docs :
following are the possible operators depending on the field type:
numeric or date fields:
-- equals
....
object fields:
-- in