Shopware advanced pricing - update rule prices via API - shopware

so I got this issue that I have some rules set up for customer groups (each per different sales channel). I then used those rules in advanced pricing tab for some of my products. Now I would like to change the advanced product price for a single rule using API request. From what I understand, it should be possible using 'product-price' endpoint, PATCH method (https://shopware.stoplight.io/docs/admin-api/8fe455ace068a-list-with-basic-information-of-product-price-resources).
I am making a request with payload like below and url https://shop-domain/api/product-price/fda10622ed67472e82d800618b0c36d1:
advanced pricing img
amazon rule img
postman request img -204 No Content
product-price endpoint img
{
"data":
{
"type": "product_price",
"id": "fda10622ed67472e82d800618b0c36d1",
"attributes": {
"productId": "675b627cb3034444af9904bb41901a32",
"ruleId": "ace571bd8e6f48c88f17a551ed1e2654",
"price": [
{
"currencyId": "b7d2554b0ce847cd82f3ac9bd1c0dfca",
"net": 115.44,
"gross": 234.50,
"linked": false
}
],
"quantityStart": 1
}
}
}
... but I am getting no effect and no actual response (response is empty, 204 - No Content). What am I missing? The ultimate goal here for me is to be able to set up different prices for different sales channels like Amazon or eBay for given products. Also, the request I present here is for single update, though it would be better if this could be a bulk request (I've tried /api/_action/sync upserts as well, but I'm not sure how it should be done - documentation here seems to be quite laconic).
The "id" that I'm using here is product price id that I got using GET method on the same endpoint - for listing all product prices from advanced pricing (last image; /api/product-price: https://swagger.docs.fos.gg/).
What am I missing here, how it should be done properly? Should I use customer groups for rules or maybe Sales Channels (if it even makes any difference here)?

Related

Can I expand the set of fields returned by the Google group members API?

I need to make a Google API call to get specific information about members of a group.
The API for fetching group members is described here: https://developers.google.com/admin-sdk/directory/v1/guides/manage-group-members
But this API only returns ONE of the fields that I require for each member. I also require first name, last name, display name, phone number, organization, job title, and department.
ALL the fields for a user are available through this API: https://developers.google.com/admin-sdk/directory/v1/guides/manage-users. But I don't want to make multiple API calls to get the user information that I need.
Is there a way to get a set of fields for the members of a group?
I have found an API parameter named "fields" which can REDUCE the number of fields returned by the "members" API: https://developers.google.com/admin-sdk/directory/v1/guides/performance#patch
But how do I INCREASE the number of fields returned?
Or, alternatively, can I make a call to the "users" API and FILTER on the group I am looking for?
I did an HTTP GET against https://admin.googleapis.com/admin/directory/v1/groups/groupKey/members.
It returned JSON in this format:
{
"kind": "directory#members",
"members": [
{"kind": "directory#member",
"id": "group member's unique ID",
"email": "liz#example.com",
"role": "MANAGER",
"type": "GROUP"
},
],
}
The "members" list does not include first name, last name, phone number, etc.
I expected an API parameter which I can use to specify which attributes to return in the "members" list.
By using a Google API batch request I was able to reduce the number of API calls to:
MEMBERS API request to get the members of a group.
BATCH API request comprised of 1000 USER API requests (due to the 1000 request limit per batch).
So, for example, a group with 2000 members takes 3 API calls in total:
Get the members of the group.
Get the attributes for the first 1000 users.
Get the attributes for the second 1000 users.
Here is the info for Google API batch requests:
https://developers.google.com/admin-sdk/directory/v1/guides/batch
And the Python Google library we are using provides a very clean wrapper:
https://googleapis.github.io/google-api-python-client/docs/batch.html

Why odata Trippinservice returns only 8 pages?

When I give the odata service url,https://services.odata.org/V4/(S(ysqt4lcalbsipb1qkoc04ryb))/TripPinServiceRW/People in browser,I only get 8 records.Why do I get only 8 records when there are total of 20 records in People entity?Is PageSize set in Trippinservice?Can anyone help me to understand this?
Yes, this service implements server-side paging.
Firstly we identify that server-side pagination is in effect from the presense of the #odata.nextLink property in the response, this is in the root of the response:
{
"#odata.context": "http://services.odata.org/V4/(S(ysqt4lcalbsipb1qkoc04ryb))/TripPinServiceRW/$metadata#People",
"#odata.nextLink": "https://services.odata.org/V4/(S(ysqt4lcalbsipb1qkoc04ryb))/TripPinServiceRW/People?%24skiptoken=8",
"value": [
... 8 records ...
]
}
We can only assUme that the page size is 8 by counting the number of records in the response or by consulting the documentation for the given service. In this case there is a $skiptoken query parameter inside the next link, in this case it happens to have a value of 8 and this corresponds to the number of records, but only by coincidence.
NOTE: %24 is a dollar sign $ that has been url encoded
~/TripPinServiceRW/People?%24skiptoken=8
In the case of the TripPin service documented in the OData Basic Tutorial, the $skiptoken value represents the number of records to skip and is a common implementation, but it is not a standard.
There is no specific mention of the server page size for the People feed in the documentation, nor is there a standard way to document $skiptoken logic at all in the $metatdata. Have a read on how and why ASP.NET WebAPI implements skiptoken: Use $skiptoken for server-driven paging
We can demonstrate this by navigating the next nextLink or altering the $orderby:
GET: ~/TripPinServiceRW/People?$skiptoken=8
{
"#odata.context": "http://services.odata.org/V4/(S(ysqt4lcalbsipb1qkoc04ryb))/TripPinServiceRW/$metadata#People",
"#odata.nextLink": "https://services.odata.org/V4/(S(ysqt4lcalbsipb1qkoc04ryb))/TripPinServiceRW/People?%24skiptoken=16",
"value": [
... 8 more records ...
]
}
The $skiptoken is now 16 in the new nextLink: ~/TripPinServiceRW/People?%24skiptoken=16. In many implementations the $skiptoken will represent the key value of the last record that was sent, but TripPin does not use this convention, we can verify that by changing the order:
Both of these responses will have $skiptoken=8 in the nextLink
GET: ~/TripPinServiceRW/People?$orderby=UserName
{
"#odata.context": "http://services.odata.org/V4/(S(ysqt4lcalbsipb1qkoc04ryb))/TripPinServiceRW/$metadata#People",
"#odata.nextLink": "https://services.odata.org/V4/(S(ysqt4lcalbsipb1qkoc04ryb))/TripPinServiceRW/People?%24orderby=UserName&%24skiptoken=8",
"value": [
... 8 records ...
]
}
GET: ~/TripPinServiceRW/People?$orderby=UserName desc
{
"#odata.context": "http://services.odata.org/V4/(S(ysqt4lcalbsipb1qkoc04ryb))/TripPinServiceRW/$metadata#People",
"#odata.nextLink": "https://services.odata.org/V4/(S(ysqt4lcalbsipb1qkoc04ryb))/TripPinServiceRW/People?%24orderby=UserName+desc&%24skiptoken=8",
"value": [
... 8 records ...
]
}
According to the specification, $skiptoken is an arbitrary token that services can use to retrieve the next page of data from a previously prepared set. The value of the $skiptoken will have special significance to the server itself and it may be an arbitrary token or reference pointing to a page in a cached resultset.
11.2.5.7 Server-Driven Paging
Responses that include only a partial set of the items identified by the request URL MUST contain a link that allows retrieving the next partial set of items. This link is called a next link; its representation is format-specific. The final partial set of items MUST NOT contain a next link.
OData clients MUST treat the URL of the next link as opaque, and MUST NOT append system query options to the URL of a next link. Services may not allow a change of format on requests for subsequent pages using the next link. Clients therefore SHOULD request the same format on subsequent page requests using a compatible Accept header. OData services may use the reserved system query option $skiptoken when building next links. Its content is opaque, service-specific, and must only follow the rules for URL query parts.
It is worth highlighting this very specific note in the specification:
OData clients MUST NOT use the system query option $skiptoken when constructing requests.
The $skiptoken is a server-side implementation and in many cases you couldn't even guess what a correct value might be. The TripPin service is a very simple demonstration API, it uses a page size of 8 to illustrate the behaviour of server-side paging, given the small size of the overall dataset (20) this is a nice arbitrary number that will result in multiple pages with the last page only partially full. That's enough to test basic compliance of server-side supporting data interfaces.
Server-side paging is designed to encourage search driven interfaces where users formulate more precise search criteria in preference to browsing through the pages 1 by 1. Virtual Scrolling is a common user interface paradigm that exploits server-side paging. Different languages and runtimes have different implementations but basically the user can scroll through a list or grid of data and when they get to the bottom there might be a link to "load more" records (behind the scenes, this will load the response from the nextLink). Sometimes this link is not displayed and the data is automatically loaded as the user approaches or reaches the end of the list.
You can still use traditional client-side paging using the $top and $skip query parameters, however some service implementations of server-side paging will still constrain the results to the fixed number of rows as defined by that servers internal logic. If you are implementing client-side paging then you may still need to use the nextLink to retrieve all the results for each client-side page of results.
Lets compare by first getting page 2, of a client-side page size of 5:
GET: ~/TripPinServiceRW/People?$skip=5&$top=5
{
"#odata.context": "http://services.odata.org/V4/(S(ysqt4lcalbsipb1qkoc04ryb))/TripPinServiceRW/$metadata#People",
"value": [
... 5 records ...
]
}
Notice that there is no #odata.nextLink property in the response, that is because the requested number of items does not exceed the server page size logic. So lets try a page size of 9. This time, to retrieve all the records for the page, we will need to make multiple queries.
The general guidance here is to recursively call the service for each of the nextLink urls in the responses, if they contain a nextLink
GET: ~/TripPinServiceRW/People?$skip=9&$top=9
{
"#odata.context": "http://services.odata.org/V4/(S(ysqt4lcalbsipb1qkoc04ryb))/TripPinServiceRW/$metadata#People",
"#odata.nextLink": "https://services.odata.org/V4/(S(ysqt4lcalbsipb1qkoc04ryb))/TripPinServiceRW/People?%24skip=9&%24top=9&%24skiptoken=8",
"value": [
... 8 records ...
]
}
GET: ~/TripPinServiceRW/People?%24skip=9&%24top=9&%24skiptoken=8
{
"#odata.context": "http://services.odata.org/V4/(S(ysqt4lcalbsipb1qkoc04ryb))/TripPinServiceRW/$metadata#People",
"value": [
... 1 record ...
]
}
When you are implementing your own OData-v4 conformant API it is important to understand this quirk and to document specifically in your API documentation what your policy or convention is with regard to server-side paging and which collections it is enabled on.
In my own implementations, I will often disable server-side paging if the request contains the client-paging token $top (and the value for $top is <= 200) but
From a client-side implementation if you see a nextLink property in the response and you didn't recieve the expected number of records, then you should query for the subsequent server-pages to fulfil your request if you are not able to implement a virtual Scroll enabled user experience.
NOTE: Normally when we discuss paging in OData v4 services the examples would include use of the $count query option.
[11.2.9 Requesting the Number of Items in a Collection]: On success, the response body MUST contain the exact count of items matching the request after applying any $filter or $search system query options...
The returned count MUST NOT be affected by $top, $skip, $orderby, or $expand.
The TripPin service DOES NOT CONFORM to this particular (and many other) clause in the specification, so I have not used that query option in this explanation.

Acumatica run Generic Inquiry via REST API

How can I run a generic inquiry that I created via Acumatica's REST API? I was using the Inventory Summary Inquiry before but it was not returning all of the data I needed so we created a Generic Inquiry to return available for shipment quantity for ALL stock items. However I can't find how to get the data from this report via the API.
UPDATE:
I've tried creating an extended endpoint service and adding my endpoint for the report as described in I210 Documentation and then hitting via the REST API (which is not shown in I210). I added all of the result fields to the fields tab of the endpoint that I need returned.
Here are the details I used:
Extended Endpoint Name: MyInventoryAvailable
Endpoint version: 6.00.001
Endpoint: GetAvailableInventory
URL: https://mycompany.acumatica.com/entity/MyInventoryAvailable/6.00.001/GetAvailableInventory?$expand=Results
When I do a PUT request using the above details, this is the response I get:
{
"message": "The request is invalid.",
"modelState": {
"": [
"The request body should not be empty."
]
}
}
UPDATE 2
Here is the setup in Acumatica for the extended endpoint:
I've tried setting up a request body but with no success:
{
"InventoryID": {
"Value": "AB-CL-60"
},
"Description": {
"Value": ""
},
"Location": {
"Value": ""
},
"QtyHardAvailable":{
"Value": 0.0
},
"QtyOnHand":{
"Value": 0.0
},
"Warehouse":{
"Value": 0.0
}
}
When sending any request body, regardless of the content I recieve this error:
"exceptionMessage": "The given key was not present in the dictionary.",
"exceptionType": "System.Collections.Generic.KeyNotFoundException",
UPDATE 3 - Inquiry Structure
Here is the structure of the inquiry:
And here are the results in Acumatica's UI:
UPDATE 4
Expanded GetAvailableInventory node:
This is how I structure Generic-Inquiries in Web-Service-Endpoints.
While other Endpoints contain any number of Mapped Objects, the Generic-Enquiry Endpoints only have
Enter-Keys, Filter, Result, and Values-for-Update
The FIELDS for the ENDPOINT are the Filters (click POPULATE -> Filters). The example above does not seem to have any filters, which is fine, so this FIELDS should be empty.
To get the data from the Generic Inquiry, a "Detail" entity is added
click the Generic Inquiry
click "+ INSERT"
Fill in form with FieldName='GetAvailableInventoryResults', ObjectName='GetAvailableInventoryResults', ObjectType=Detail
Save
Now, add the results wanted by clicking on 'GetAvailableInventoryResults', then FIELDS (opens a popup). In the popup, select 'Result' and add all the fields you want. Don't select "Row Number" and "Selected" as these are not needed and can cause errors. SAVE.
To access the ENDPOINT, do a PUT to
.../GetAvailableInventory?$expand=GetAvailableInventoryResults
with a BODY of
{}
since this ENDPOINT does not define any Filters, but a PUT requires this to exist.
Why do I use "GetAvailableInventoryResults"? Well, because I ran into issues with multiple Generic-Inquiry Endpoint's having Details with the same name, so I make sure they are all unique.
Use GET instead of PUT. Your requirements fall under this. I supposed Generic Inquiry <> Inquiry Form. Hence the different outcome between GET vs PUT.

Dialogflow / Actions on Google: Provide dynamic response data for link out suggestions

I've tried to implement an Dialogflow app (Actions on Google) and it works quite well so far. However: does anyone know if it is possible to define further action parameters / context via node.js, so I can use them somehow to create dynamic "link out suggestions" in Dialogflow?
In Detail: I try to request some parameters from the users, map them on a set of urls (=implemented as some kind of database) and then write the result url into the json response. Goal: include these response url as $url, #deeplink.url (or similar) in Dialogflow's "Response > Google Assistant > Enter URL".
Is this possible in any way? Thank you in advance.
UPDATE: I also tested the approach of building a rich reponse, but it does not seem to work. Example:
const richResponse = app
.buildRichResponse()
.addSimpleResponse('Flight from ' + origin + ' to' + destination)
.addSuggestions("Find your flight:")
.addSuggestions("Basic Card", "List", "Carousel")
.addSuggestionLink("Search now", url);
(app is an instance of require('actions-on-google').DialogflowApp)
However, he seems to stop after "addSimpleResponse".
Yes. You can create a context in your webhook, and include parameters in that context that contain the values that you want. To use your example, you could create a context "deeplink" and set a parameter in it named "url" with the URL you're going to link to. You should probably also have a "title" parameter, since the Link Out Suggestion and Basic Card requires a title or website name in addition to the link.
Creating a context is fairly simple, but depends on exactly how you're generating the JSON. If you're using the actions-on-google library for node.js, you would create it with a command something like
var contextParameters = {
title: "Example Website!",
url: "http://example.com/"
};
app.setContext( "deeplink", 1, contextParameters );
If you're creating the response JSON yourself, you will have a contextOut array with the context objects you want to set. This portion of the JSON might look something like
"contextOut": [
{
"name": "deeplink",
"lifespan": 1,
"parameters": {
"title": "Example Website!",
"url": "http://example.com/"
}
}
]
Then, in the fields for the Link Out or Basic Card, you would reference them as #deeplink.title and #deeplink.url. For a Link Out, it might look something like this:
However, once you're doing fulfillment, sometimes it becomes easier to generate the VUI and GUI elements in the webhook instead of setting them as part of the Dialogflow builder. This is particularly true if you have a varying number of cards or carousel items that you want to generate.
The Actions on Google documentation provides the various UI elements that can be returned along with sample JSON and node.js code to generate each. These are the same elements that Dialogflow offers through the Actions on Google response tab - just that you can generate them from your webhook instead.

Determine total pages with Google list method

I'm working with the Google Blogger API and am finding its forcing pagination on me when retrieving a list of blog posts. It looks like several of the Google APIs offer a List method to return a list of [items]. The request has a maxResults parameter, which defaults to various numbers depending on the API (apparently 10 for Blogger).
The problem is I'm not seeing it returning the total number of posts or pages and my app has a progress bar to show the percentage of total posts that it has processed.
So I need to know how many posts there are total.
I found that the YouTube API's response for PlayListItems includes a pageInfo object with the total number of results in it.
Is there something like this that I'm just missing for Blogger Posts or do they really require paging without providing a way to get the total page count?
Posts: list returns a special type of response. It includes only the next page token and a list of the posts. The same is true for Pages.
{
"kind": "blogger#postList",
"nextPageToken": string,
"items": [
[posts Resource][2]
]
}
Most of the other google APIs will return totalResults, Which is the total number of rows that the request could return with out paging. Blogger doesn't do this as shown above. You can get around it in the following manner.
Blogs: get returns a blog Resource will return the information about the blog including the number of posts and pages it contains. This is the only way to my knowledge to get a full result of the number of rows.
"posts": {
"totalItems": 395,
"selfLink": "https://www.googleapis.com/blogger/v3/blogs/1969422610982987741/posts"
},
"pages": {
"totalItems": 1,
"selfLink": "https://www.googleapis.com/blogger/v3/blogs/1969422610982987741/pages"
},

Resources