Shopify add cart properties. How do this properties work? It disappears after page refresh - shopify

I am setting properties when adding to cart.
Ex:
var formdata=[
"items":{
id:123456,
quantity:1
properties:{'flag':true}
}
];
added using api : /cart/add.js
Details I get from cart.js without refresh
response from : /cart/add.js and cart.js
[
{
"id": 32423423423423,
"properties": {
"flag": true
},
"quantity": 1,
"variant_id": 42705234345345,
}
]
The above items get added successfully to cart. After adding I again fetch the cart details and It has this properties value.But when I refresh the page cart items properties does not have any value.
Ex Currently I am getting this only when page is refreshed:
response from cart.js after page refresh
properties:{
Ref: 0
}
What this properties is?
Why is this happening? If worked, will this properties be available on order create webhook? It only disappears when refreshed. Moreover main reason to add this properties is to receive this properties in order-create webhook to distinguish from normal order. If anyone having other alternative please suggest.

Adding a product to the cart like so:
fetch('/cart/add.js', {
method: "post",
headers: {
"content-type": "application/json"
},
body: JSON.stringify({
items: [
{
quantity: 1,
id: 33116507373620,
properties: {
'flag': true
}
}
]
})
})
And getting the cart.js like so:
fetch('/cart/add.js').then(res => res.json()).then(res => console.log(res))
Will get you result like so:
{
...
"items": [
{
"id": 33116507373620,
"properties": {
"flag": true
},
"quantity": 1,
...
}
],
...
}
From there on what you are doing to not get this result I'm not sure, since this is working/tested and there is no issue.
Please double check if you are targeting the correct object once you get the cart.js response. (there is no properties direct object, it's under items[0].properties in this case)

Related

Shopware 6: how to delete all products via admin api

How to delete all products via admin api?
To achieve the goal i try to use the Bulk Payloads | Deleting entities
The doc says:
[...] To delete entities, the payload of an operation contains the IDs. [...]
Questions:
to delete all products i have to read first all product.id's?
or is there a alternative way with a type of "wildcard"?
My current request body (using Postman) ...:
{
"delete-product": {
"entity": "product",
"action": "delete",
"payload": []
}
}
... response with (products remains in db):
{
"extensions": [],
"success": true,
"data": {
"delete-product": {
"extensions": [],
"result": []
}
},
"deleted": [],
"notFound": []
}
EDIT #1
With id's provided...:
...
const obj = {
"delete-products": {
"entity": "product",
"action": "delete",
"payload": [
{"id": "73af65014974440b95450f471b3afed8"},
{"id": "784f25a29e034fad9a416923f964ba8a"}
]
}
}
apiClient.request({
"url": "/_action/sync",
"method": "POST",
obj
})
...
... the request fails in class Symfony\\Component\\Serializer\\Encoder\\JsonDecode with message:
detail: "Syntax error"
Debugging the request, payload is missing (empty content):
What is wrong with the configuration of the /api/_action/sync call?
Indeed, what it means is that you will need a low impacting query to get all product id's, store it into a variable & delete them. Use includes:["id"] filter to just get the ID's.
Here is an example of me deleting some products in Postman.
Request body:
{
"delete-product": {
"entity": "product",
"action": "delete",
"payload": {{gen_dynamic_products}}
}
}
Pre-request script (you'll need to adjust this sightly to get your ID's):
const map = new Array(30).fill(0).map((val, index) => {
return { id: pm.environment.get('gen_product_list_sub_' + index) };
});
pm.variables.set('gen_dynamic_products', JSON.stringify(map));
to delete all products i have to read first all product.id's?
Yes, that is what you'll have to do. This is necessary to maintain the extendibility of the platform. The core or other plugins may react to the deletion of products by subscribing to an entity lifecycle event. This event includes the id of the deleted entity. Hence why it is necessary to explicitly provide the ids of the entities in the first place.

How to update the Strapi GraphQL cache, after creating new data?

How to update the cache, after creating new data?
Error message from Apollo
Store error: the application attempted to write an object with no provided id but the store already contains an id of UsersPermissionsUser:1 for this object. The selectionSet that was trying to be written is:
{
"kind": "Field",
"name": { "kind": "Name", "value": "user" },
"arguments": [],
"directives": [],
"selectionSet": {
"kind": "SelectionSet",
"selections": [
{ "kind": "Field", "name": { "kind": "Name", "value": "username" }, "arguments": [], "directives": [] },
{ "kind": "Field", "name": { "kind": "Name", "value": "__typename" } }
]
}
}
Nativescript-vue Front-end Details
1- Watch Book Mobile app in action on YouTube: https://youtu.be/sBM-ErjXWuw
2- Watch Question video for details on YouTube: https://youtu.be/wqvrcBRQpZg
{N}-vue AddBook.vue file
apolloClient
.mutate({
// Query
mutation: mutations.CREATE_BOOK,
// Parameters
variables: {
name: this.book.name,
year: this.book.year,
},
// HOW TO UPDATE
update: (store, { data }) => {
console.log("data ::::>> ", data.createBook.book);
const bookQuery = {
query: queries.ALL_BOOKS,
};
// TypeScript detail: instead of creating an interface
// I used any type access books property without compile errors.
const bookData:any = store.readQuery(bookQuery);
console.log('bookData :>> ', bookData);
// I pin-pointed data objects
// Instead of push(createBook) I've pushed data.createBook.book
bookData.books.push(data.createBook.book);
store.writeQuery({ ...bookQuery, data: bookData })
},
})
.then((data) => {
// I can even see ID in Result
console.log("new data.data id ::::: :>> ", data.data.createBook.book.id);
this.$navigateTo(App);
})
.catch((error) => {
// Error
console.error(error);
});
What are these "Book:9": { lines in the cache?
console.log store turns out:
"Book:9": {
"id": "9",
"name": "Hadi",
"year": "255",
"__typename": "Book"
},
"$ROOT_MUTATION.createBook({\"input\":{\"data\":{\"name\":\"Hadi\",\"year\":\"255\"}}})": {
You can see all front-end GitHub repo here
Download Android apk file
Our goal is to update the cache. Add Book Method is in here:
https://github.com/kaanguru/mutate-question/blob/c199f8dcc8e80e83abdbcde4811770b766befcb5/nativescript-vue/app/components/AddBook.vue#L39
Back-end details
However, this is a frontend question a running Strapi GraphQL Server is here: https://polar-badlands-01357.herokuapp.com/admin/
GraphQL Playground
USER: admin
PASSWORD: passw123
You can see GraphQL documentation
I have so much simple Strapi GrapQL Scheme:
If you want to test it using postman or insomnia you can use;
POST GraphQL Query URL: https://polar-badlands-01357.herokuapp.com/graphql
Bearer Token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwiaWF0IjoxNTkwODI3MzE0LCJleHAiOjE1OTM0MTkzMTR9.WIK-f4dkwVAyIlP20v1PFoflpwGmRYgRrsQiRFgGdqg
NOTE: Don't get confused with $navigateTo() it's just a custom method of nativescript-vue.
It turns out;
all code was correct accept bookData.push(createBook);
// HOW TO UPDATE
update: (store, { data }) => {
console.log("data ::::>> ", data.createBook.book);
const bookQuery = {
query: queries.ALL_BOOKS,
};
// TypeScript detail: instead of creating an interface
// I used any type access books property without compile errors.
const bookData:any = store.readQuery(bookQuery);
console.log('bookData :>> ', bookData);
// I pin-pointed data objects
// Instead of push(createBook) I've pushed data.createBook.book
bookData.books.push(data.createBook.book);
store.writeQuery({ ...bookQuery, data: bookData })
},
})
Typescipt was helping
The point is; I shouldn't trust TypeScript errors, or at least I should read more about what it really says.
Typescript just asked me to be more specific while saying: Property 'push' does not exist on type 'unknown'
TypeScript was trying to tell me I need to be more specific while calling ROOT_MUTATION data. It said: Cannot find name 'createBook' But again I ignored it.
Solution Github Branch
https://github.com/kaanguru/mutate-question/tree/solution
Sources
how to update cache
Create interface for object Typescript

How to use dojox/data/JsonRestStore with dojox/grid/LazyTreeGrid?

I have now this code:
define([
"dojo/_base/declare",
"dojox/data/JsonRestStore",
"dojox/grid/LazyTreeGrid",
"dojox/grid/LazyTreeGridStoreModel"
], function(
declare,
JsonRestStore,
LazyTreeGrid,
LazyTreeGridStoreModel
) {
var layout = { ... },
store = new JsonRestStore({
target: "/api/items" // for example
limitParam: "limit",
offsetParam: "offset"
}),
model = new LazyTreeGridStoreModel({
serverStore: true,
store: store,
childrenAttrs: [ "children" ]
});
return declare("CustomTreeGrid", [ LazyTreeGrid ], {
treeModel: model,
structure: layout
});
});
My widget send thousand requests to target URL after startup and freeze my browser. How to fix wrong behavior and save compatibility with RESTful API?
Solution with QueryReadStore work, but not in my situation - Django REST Framework return page with API declaration on GET requests.
Server return data in JSON format:
{
"items": [ ] //Array of items
"identifier": "id",
"numRows": 12 // Total count of items
}
Also I change the server response for returning array. Response headers also contain key "Content-Range: 0-2/3" (for example) and it's not work for me.
Server response headers:
HTTP 200 OK
Allow: GET, POST, HEAD, OPTIONS
Content-Range: items 0-1/2
Content-Type: application/json
Vary: accept
Server response body:
[
{
"id": 1,
"children": false,
"name": "name1"
},
{
"id": 2,
"children": false,
"name": "name2"
}
]
It is pretty hard to make a jsfiddle out of it because you need the server part as well.
I found this implementation: https://github.com/jeremyg484/dojo-json-rest-store
It uses a combination of : dojo.store.Cache, dojo.store.JsonRest, dojo.store.Memory and dojo.data.ObjectStore
Maybe you can do something with it...
See how it is used :
myStore = dojo.store.Cache(dojo.store.JsonRest({target:"usstates/"}), dojo.store.Memory());
grid = new dojox.grid.DataGrid({store: dataStore = dojo.data.ObjectStore({objectStore: myStore})

updating inventory quantity with PUT returns error

Here is the body
{
"product": {
"id": 1202316036,
"title": "cricket bat for sale",
"variants":[
{
"inventory_quantity": 500
}
]
}
}
This returns the following error
{
"errors": {
"base": [
"The variant 'Default Title' already exists."
]
}
}
But where as the updating the title seems to be working fine. Here is the body
{
"product": {
"id": 1202316036,
"title": "cricket bat for sale"
}
}
I am sure that PUT header(Content-Type: application/json) are set properly. Because updating title does work. How should I go about updating inventory management
ps: I am using POSTMAN for using shopify API
So you do need the variant id otherwise Shopify thinks you are creating a new variant. Also your variants need to have been set up for Shopify to manage their inventory. e.g.
var product = {
product:{
id: productId,
variants: [
{
id:5991257025,
inventory_management : "shopify",
inventory_quantity:20
},
{
id:5991257089,
inventory_management : "shopify",
inventory_quantity:26
}
]
}
};
I'm not sure if you can do multiple variants per call but to update a single variant's inventory quantity you'd do it like:
var payload = JSON.stringify({
variant: {
id: variantId,
inventory_quantity: qty
}
});
and then put that to "https://myshopifydomain/admin/variants/" +variantId + ".json";
possibly all you need to do is add the variant id for each variant you are updating. Your variant ids can be gotten by GETting the json for your items.

Ember-data hasMany relationship not working (JSONAPIAdapter)

I'm using Ember-Data v.1.13.9 with Ember-CLI v.1.13.8. I'm using the JSONAPIAdapter adapter.
I have a problem with a hasMany relationship. I can see from the Ember inspector that both the main record and the related record are being loaded into the store. However, the relationship doesn't seem to be there since I cannot access the related records details in my template.
models/invoice.js
export default DS.Model.extend(
{
invNum : DS.attr('string'),
created : DS.attr('date', {defaultValue: function() { return new Date(); }}),
clientId : DS.attr('number'),
userId : DS.attr('number'),
details : DS.hasMany('invoice-detail', {async : true}),
});
models/invoice-detail.js
export default DS.Model.extend(
{
invoice : DS.belongsTo('invoice', {async : true}),
detail : DS.attr('string'),
amount : DS.attr('number'),
vat : DS.attr('number'),
});
my JSON data: (URL: /accounts/invoices/1)
{
"data": {
"id": 1,
"attributes": {
"inv-num": "A0011000001",
"created": "November, 01 2000 00:00:00",
"user-id": 2,
"client-id": 14,
"relationships": {
"details": {
"data": [
{
"id": 1,
"type": "invoice-detail"
}
]
}
}
},
"type": "invoice"
},
"included": [
{
"id": 1,
"attributes": {
"amount": 3000,
"detail": "Stage 1 delivery of 3Com Reseller Locator to\r\nFoundation Network LTD",
"vat": 525
},
"type": "invoice-detail"
}
]
}
I've tried accessing the details related array directly:
{{#each model.details as |detail index|}}
{{index}} : {{detail.detail}} £{{detail.amount}} (£{{detail.vat}} vat)
{{/each}}
And by using a controller: invoice/controller.js
export default Ember.Controller.extend({
invoiceDetails : function()
{
var invoice = this.get("model");
var details = invoice.get("details");
Ember.Logger.log("invoiceDetails",invoice,details);
return details;
}.property('model.details'),
});
and
{{#each invoiceDetails as |detail index|}}
{{index}} : {{detail.detail}} £{{detail.amount}} (£{{detail.vat}} vat)
{{/each}}
Neither is providing me with the data that I require.
What am I doing wrong?
A second related issue I am having is that I can't get it to reload data from the server. the {reload:true} makes no difference. Looking at the network traffic I can see that no call to the server is made for second and subsequent visits to this route.
invoice/route.js
export default Ember.Route.extend({
model: function(params) {
return this.store.findRecord('invoice', params.id, { reload: true });
}
})
What I actually want to do here is have one route which retrieves a list of invoices (without the details part - so it's quick to retrieve since I do not need the details on the list page). Then, when I drill down to a specific invoice, make a call to the server to get the full details for that invoice. My plan was to use the shouldReloadRecord function to check if I have details attached to this record or not. If so, use the copy from the store, if not, go to the server and then overwrite the limited "list" record I got initially. As a stepping stone in that direction I figured that just setting {reload:true} in the route would force all requests to go back to the server.
I guess I've misunderstood something somewhere...?