Acumatica REST API - StockItem - how to expand Price Item in request - acumatica

I am using the Acumatica REST endpoint https://sandbox.kimballinc.com/AcumaticaERP/entity/Default/6.00.001 in my application
I am using the URL https://sandbox.kimballinc.com/AcumaticaERP/entity/Default/6.00.001/StockItem?$filter=InventoryID eq '123456'&$expand=WarehouseDetails to fetch info about a Product and to get complete warehouse details
My query is how to expand and get Price/CostInfo details in the response

Expand should be used for the arrays declared inside the entity in the web service endpoint:
Price/CostInfo is not an array so it can't be expanded. The default endpoint doesn't contain those fields so you'll need to extend the endpoint and add them:
Select the StockItem entity and use POPULATE button to add the fields:
Extended endpoint requires that you specify a different endpoint name:
In this example I choose DefaultPlus so I need to connect to:
https://xyz/AcumaticaERP/entity/DefaultPlus/6.00.001/StockItem
Instead of:
https://xyz/AcumaticaERP/entity/Default/6.00.001/StockItem
The added fields will be part of the GET response for StockItem, no special parameter is required for that.

I took a look at your site and noticed that you are using Acumatica 2018 R2.
I would then recommend that you use the latest version of the endpoint 18.200.001 as there are more field there by default.
If I saw correctly some of the fields for the Price/Cost Info are already in the main entity as they have a relation 1:1 to it.
To resume it using the latest version of the endpoint would allow you to see these field without the need to expand anything.

Related

Display customer specific information on product detail page - what about the caching?

We want to display customer (actually customer-group) specific information on product detail pages in Shopware 6.
There seems to be the HTTP cache and we are afraid that the page would be cached if a specific customer group displays the page and the information would be leaked to non-customers.
Is this assumption correct?
The documentation does not reveal much information about this.
Is there a way to set specific cache tags, so that the information is only displayed to the correct customer group?
Or do we need to fetch the data dynamically via AJAX?
Bonus question: Can the HTTP cache be simulated in automatic tests to ensure the functionality works?
What I found out so far:
The is annotation #httpCache for controller, which seems to control whether a page is cached or not
The cache key is generated in \Shopware\Storefront\Framework\Cache\HttpCacheKeyGenerator::generate. It take the full request URI into account, and some cacheHash which is injected. I believe it would not take the customer group into account
Maybe this generate() method could be decorated, but I am not sure if that is the right way.
There is a cookie being set sw-cache-hash which influences the caching. It takes the customer into account.
sw-cache-hash is created here:
if ($context->getCustomer() || $cart->getLineItems()->count() > 0) {
$cookie = Cookie::create(self::CONTEXT_CACHE_COOKIE, $this->buildCacheHash($context));
$cookie->setSecureDefault($request->isSecure());
$response->headers->setCookie($cookie);
} else {
$response->headers->removeCookie(self::CONTEXT_CACHE_COOKIE);
$response->headers->clearCookie(self::CONTEXT_CACHE_COOKIE);
}
So as soon you are logged in or have some items in the cart, a different cache hash is used. This depends on the following, but not on the customer group it self:
private function buildCacheHash(SalesChannelContext $context): string
{
return md5(json_encode([
$context->getRuleIds(),
$context->getContext()->getVersionId(),
$context->getCurrency()->getId(),
]));
}
Additionally there is the notion of cache-invalidation states, that describe when the caching should not be used.
You can configure that inside the shopware.yaml config file for the http-cache as a whole or on route level for the store-api routes.
From the default config inside platform:
shopware:
cache:
invalidation:
http_cache: ['logged-in', 'cart-filled']
product_listing_route: []
As you can see by default the http-cache won't be used if a user logs in or has something in his cart.
As you can see in the last code snippet, it takes into account the active Rule ids.
This means that if you create a rule (through Settings > Rule Builder) that is active on a certain group, but not on another or no group, it will be taken into account & create a different cache hash for the different customer groups.

How to pass a document's ID using Azure CosmoDB?

I am creating a simple CRUD app to learn Azure. I have created a logic app (standard model) and my APIs are designed using the workflow designer. I also have a CosmoDB to hold each object.
My GET API, that gets all the documents, looks like this:
And my GET API, that gets only one document, looks like this:
Here is what my CosmosDB looks like with the ID of the item that is successfully return when statically called:
So what do I need to replace the static ID with, in the *Document ID input so that I can pass in different IDs?
I have looked at the docs and it suggests documentId, but when I type this in I get this error:
Thanks!
Thank you #404 , posting your suggestion as an answer to help other community members.
" You should know the id you want to retrieve from the flow that feeds into the Get a document block (unless it's static). Since you only have a HTTP trigger your id should be supplied through that. As example by passing the id in the url as query parameter which you then refer to in your Document ID field."
Trigger a post request to logic app with Document ID in request body.
Try as below:

Acumatica PXDimension Selector Causing Endpoint to Fail. - Rest Api -

I am trying to upload a file via the standard endpoint /entity/default/18.200.001/Project/projectname/files/filename . The project DAC extension ContractCD itself has a PXRestrictor where [PXRestrictor(typeof(Where>>), "Projects are not of current Branch")] .
The restrictor is causing the endpoint to fail if the project we are uploading does not have the same default branch from the User Profile Screen SM203010. I want to add a condition to the PXRestrictor similar to [PXRestrictor(typeof(Where,Or>>) or any other suggestion?
Starting from Acumatica 19r2 you can actually specify a "Current" branch for a REST API request.
Try adding a special header PX-CbApiBranch with branch name (e.g. "Products Retail") as a value.

What is the Sharepoint Document Location endpoint really returning?

I'm trying to get the OneNote notebook information that is linked to my organization's CRM accounts. Each account has a OneNote book created for it that can be accessed inside of CRM.
From what I understand, I can use the SharePointDocumentLocation endpoint (found here: https://learn.microsoft.com/en-us/dynamics365/customer-engagement/web-api/sharepointdocumentlocation?view=dynamics-ce-odata-9) to get the location of the specific file if I ask for location type to be 1.
However, SharePointDocumentLocationId and SiteCollectionId don't seem to be pointing to anything on my company's sites. Should I be getting my data somewhere else?
I started searching through my company's SharePoint structure to see if I can get any hints as to where these documents may be located. My initial Postman request (getting the sites off of the root site) don't show the site that hosts our CRM documents (sites/crmdocs). I was able to find where this was stored eventually, but trying to get the OneNote notebooks stored there returns an error since we have more than 20,000 notebooks there, so I can't fetch them all. As far as I know, I'm able to get notebooks if I have the specific ID I want.
Once I fetch the CRM information, I try to send a request like this:
https://graph.microsoft.com/v1.0/sites/{myCompanyUrl},{siteCollectionId},{sharepointDocumentLocationId}/onenote/notebooks/
SiteCollectionId and SharePointDocumentLocationId are from my CRM SharePointDocumentLocation request
The error I receive is:
The requested site was not found. Please check that the site is still accessible.
Assuming your environment is using the out of the box sharepoint site and sharepoint document location hierarchy, you can access One Note files using the following link structure:
[SharePointAbsoluteUrl]/[EntityLogicalName]/[RelativeUrl]_[RegardingObjectId]/[RelativeUrl]
How to get [SharePointAbsoluteUrl] :
Querying for sharepointdocumentlocations is actually not enough because Dynamics 365 stores this information in another entity called sharepointsite. This is how you can obtain it:
var query = new QueryExpression("sharepointsite")
{
ColumnSet = new ColumnSet("absoluteurl")
};
query.Criteria.AddCondition("IsDefault", ConditionOperator.Equal, true);
var entityCollection = _service.RetrieveMultiple(query);
var absoluteUrl = entityCollection[0].Attributes["absoluteurl"];
In Web API it is equivalent to:
GET https://[Your Org]/api/data/v9.0/sharepointsites?$select=absoluteurl&$filter=isdefault%20eq%20true
There can only be a default sharepoint site so this query will return a single record.
How to get the remaining parts:
Fetch for sharepointdocumentlocations that have Location Type dedicated to One Note Integration:
var query = new QueryExpression("sharepointdocumentlocation")
{
ColumnSet = new ColumnSet("regardingobjectid", "relativeurl")
};
query.Criteria.AddCondition("locationtype", ConditionOperator.Equal, 1);
var entityCollection = _service.RetrieveMultiple(query);
In Web API it is equivalent to the following get request, don't forget to add add Prefer: odata.include-annotations="*" to your HTTP Request Headers so that it gets the lookup lookuplogicalname field:
GET https://[Your Org]/api/data/v9.0/sharepointdocumentlocations?$select=relativeurl,_regardingobjectid_value&$filter=locationtype%20eq%201
This query can return many records, I've only used the first one in the examples below for explanation purposes.
[EntityLogicalName] will be your ((EntityReference)entityCollection[0].Attributes["regardingobjectid"]).LogicalName;
In Web Api will be your value._regardingobjectid_value#Microsoft.Dynamics.CRM.lookuplogicalname value.
[RelativeUrl] will be your entityCollection[0].Attributes["relativeurl"];
In Web Api will be your value.relativeurl value.
[RegardingObjectId] can be obtained with this expression ((EntityReference)entityCollection[0].Attributes["regardingobjectid"]).Id.ToString().Replace("-", "").ToUpper();
In Web Api id will be your _regardingobjectid_value value and you have to remove dashes and convert it to upper case in whatever language you are doing the request.
You should end up with an URL like this https://mycompany.sharepoint.com/account/A Datum Fabrication_A56B3F4B1BE7E6118101E0071B6AF231/A Datum Fabrication

Which AMP extensions can fetch a response from an endpoint?

What AMP extensions can be used to get a response from the server in the form of variable that can be used later, such as in a template or as a parameter to an attribute?
amp-access
The authorization endpoint of amp-access can return "a free-form JSON object":
Here’s a small list of possible ideas for properties that can be returned from the Authorization endpoint:
Metering info: maximum allowed number of views and current number of views.
Whether the Reader is logged in or a subscriber.
A more detailed type of the subscription: basic, premium
Geo: country, region, custom publication region
amp-form
amp-form "allows publishers to render the responses using Extended Templates". The response is expected to be a valid JSON Object. Try the "Hiding input fields after success" demo in the amp-form sample to see it in action.
amp-list
amp-list fetches "content dynamically from a CORS JSON endpoint and renders it using a supplied template". The response must be a JSON object that contains an array property "items".
In addition to {{variable}} substitutions in Mustache templates, you can also use AUTHDATA(variable) elsewhere.
amp-live-list (not quite)
amp-live-list is a "wrapper and minimal UI for content that updates live in the client instance as new content is available in the source document". The page will re-fetch itself, giving the server a change to send new content. If new content is found, AMP will populate a <div items> element with the new (HTML) items. You can't use that as a variable.
It's name doesn't really suggest it, but I think you want AMP-list
https://github.com/ampproject/amphtml/blob/master/extensions/amp-list/amp-list.md
Fetches content dynamically from a CORS JSON endpoint and renders it using a supplied template.

Resources