Discussions
Add Commerce item to cart - 403 on second Order/_execute UpdatePricing
Hello,
Due to a bug in ProductDisplay list Addtocart functionality (ZD 267095) I am trying to implement my own. Here is my process:
Create cart (assume no existing cart for this example):
const user = await AVICapiData(`/api/Person/${uid}`);
var bid = user["PrimaryOrganization"]["OrganizationPartyId"];
if (bid == undefined) { bid = uid; }
const cartpost = {
"$type": "Asi.Soa.Commerce.DataContracts.CartData, Asi.Contracts",
"UserId": uid,
"ComboOrder": {
"$type": "Asi.Soa.Commerce.DataContracts.ComboOrderData, Asi.Contracts",
"Order": {
"$type": "Asi.Soa.Commerce.DataContracts.OrderData, Asi.Contracts",
"Lines": {
"$type": "Asi.Soa.Commerce.DataContracts.OrderLineDataCollection, Asi.Contracts",
"$values": []
},
"SoldToCustomerParty": {
"$type": "Asi.Soa.Commerce.DataContracts.CustomerPartyData, Asi.Contracts",
"PartyId": uid
},
"BillToCustomerParty": {
"$type": "Asi.Soa.Commerce.DataContracts.CustomerPartyData, Asi.Contracts",
"PartyId": bid
},
"OriginatorCustomerParty": {
"$type": "Asi.Soa.Commerce.DataContracts.CustomerPartyData, Asi.Contracts",
"PartyId": uid
},
"Currency": {
"$type": "Asi.Soa.Core.DataContracts.CurrencyData, Asi.Contracts",
"CurrencyCode": "AUD",
"DecimalPositions": 2
},
"SourceCode": ""
},
"Currency": {
"$type": "Asi.Soa.Core.DataContracts.CurrencyData, Asi.Contracts",
"CurrencyCode": "AUD",
"DecimalPositions": 2
},
},
"UpdateInformation": {
"$type": "Asi.Soa.Core.DataContracts.EntityUpdateInformationData, Asi.Contracts",
"CreatedBy": uid,
"CreatedOn": new Date().toISOString(),
"UpdatedBy": uid,
"UpdatedOn": new Date().toISOString()
}
};
return await AVICapiData("/api/cart", cartpost, "POST");
That is a pretty basic empty cart, of note: I set the Bill to ID to the organisation.
I get the item data from ItemSummary (also tried Item endpoint), pretty straight forward const itemresult = await AVICapiData(`/api/ItemSummary/${productID}`);
I wrap that item data in a basic OrderLine structure:
order["Lines"]["$values"].push(createOrderLine(itemresult, orderlines+1));
function createOrderLine(itemData, lineno) {
return {
"$type": "Asi.Soa.Commerce.DataContracts.OrderLineData, Asi.Contracts",
"OrderLineId": self.crypto.randomUUID(),
"Item": itemData,
"QuantityOrdered": {
"$type": "System.Nullable`1[[Asi.Soa.Commerce.DataContracts.QuantityData, Asi.Contracts]], mscorlib",
"Amount": 1
},
"LineNumber": lineno,
"SourceCode": "",
"CanCombine": true,
"UsesPriceGroup" : true
}
}
now I have my order object wrapped and ready to be UpdatePricing
order = await AVICapiData("/api/Order/_execute", {
"$type": "Asi.Soa.Commerce.DataContracts.OrderPriceUpdateRequest, Asi.Contracts",
"EntityTypeName": "Order",
"OperationName": "UpdatePricing",
"Order": order
}, "POST");
Now, if I add this updated order object to the comboorder and PUT to /api/cart, the pricing will be incorrect...
That is with a single Order/_execute. Pricing is incorrect, and if you try to checkout with this cart you will get
So I UpdatePricing on the returned order object, which should then give me correct pricing. However if you use BillToCustomerParty = Organisation ID, I get 403 after the second UpdatePricing.
If I use BillToCustomerParty = user ID and change "Users who can bill to their organisation = All users", I can double UpdatePricing, see the correct cart, and no problem.
For some reason when Adding to cart from ItemDetail, it is able to add to cart without problem. If someone is able to point out any obvious flaw in what I am doing that would be massively useful. Or if it was possible to get a fiddler dump of someone on the latest update doing Add to Cart from ItemDetail with the following setup:
- Settings -> Contacts -> General -> Users who can bill to their organisation: All users - organization selected by default
- Add Pricing Group on the item -> Add new pricing group -> Group Type -> Member Type
Hopefully that will give me some insight in to what is happening behind the scenes, and will show me what steps if any I am missing.
Thank you for your time and assistance.
Hello again,
I received a very useful suggestion of setting the BillToCustomerParty to the orgID after getting the initial pricing. I tried 3 scenarios. The /Person/ call is when the BillToCustomerParty changes, as I use this snippet to modify the order to change the bill to:
async function AVICchangeBillToOrg(uid, order) {
// get user info, OrgID
const user = await AVICapiData(`/api/Person/${uid}`);
var oid = user["PrimaryOrganization"]["OrganizationPartyId"];
if (oid == undefined) { return order; }
order["BillToCustomerParty"]["PartyId"] = oid;
order = await AVICapiData("/api/Order/_execute", {
"$type": "Asi.Soa.Commerce.DataContracts.OrderPriceUpdateRequest, Asi.Contracts",
"EntityTypeName": "Order",
"OperationName": "UpdatePricing",
"Order": order
}, "POST");
return order;
-
UpdatePricing, Change BillToCustomerParty, UpdatePricing again - 403
-
UpdatePricing, UpdatePricing, Change BillToCustomerParty, UpdatePricing - 403
-
UpdatePricing, UpdatePricing, PUT cart, GET cart, extract order from cart, change BillToCustomerParty, UpdatePricing - 403
I've run out of leads.
If anyone wants to play with adding items to cart, here is a self contained snippet you can run in the browser dev console. It should be pretty easy to read/follow along/modify. Calling the function like so: await AVICaddToCart("PRODUCT_CODE");
will attempt to add that product in to the currently logged in user's cart. Call that in the dev console after pasting the following in to the dev console:
async function AVICapiData(endpoint, data=null, method="GET") {
var opts = {
method: method,
headers: {
"Content-Type": "application/json",
"RequestVerificationToken": document.getElementById("__RequestVerificationToken").value
}
}
if (data != null) { opts["body"] = JSON.stringify(data); }
const response = await fetch(endpoint, opts);
return await response.json();
}
function createOrderLine(itemData, lineno) {
return {
"$type": "Asi.Soa.Commerce.DataContracts.OrderLineData, Asi.Contracts",
"OrderLineId": self.crypto.randomUUID(),
"Item": itemData,
"QuantityOrdered": {
"$type": "System.Nullable`1[[Asi.Soa.Commerce.DataContracts.QuantityData, Asi.Contracts]], mscorlib",
"Amount": 1
},
"LineNumber": lineno,
"SourceCode": "",
"CanCombine": true,
"UsesPriceGroup" : true
}
}
async function AVICcreateCart(uid) {
const cartpost = {
"$type": "Asi.Soa.Commerce.DataContracts.CartData, Asi.Contracts",
"UserId": uid,
"ComboOrder": {
"$type": "Asi.Soa.Commerce.DataContracts.ComboOrderData, Asi.Contracts",
"Order": {
"$type": "Asi.Soa.Commerce.DataContracts.OrderData, Asi.Contracts",
"Lines": {
"$type": "Asi.Soa.Commerce.DataContracts.OrderLineDataCollection, Asi.Contracts",
"$values": []
},
"SoldToCustomerParty": {
"$type": "Asi.Soa.Commerce.DataContracts.CustomerPartyData, Asi.Contracts",
"PartyId": uid
},
"BillToCustomerParty": {
"$type": "Asi.Soa.Commerce.DataContracts.CustomerPartyData, Asi.Contracts",
"PartyId": uid
},
"OriginatorCustomerParty": {
"$type": "Asi.Soa.Commerce.DataContracts.CustomerPartyData, Asi.Contracts",
"PartyId": uid
},
"Currency": {
"$type": "Asi.Soa.Core.DataContracts.CurrencyData, Asi.Contracts",
"CurrencyCode": "AUD",
"DecimalPositions": 2
},
"SourceCode": ""
},
"Currency": {
"$type": "Asi.Soa.Core.DataContracts.CurrencyData, Asi.Contracts",
"CurrencyCode": "AUD",
"DecimalPositions": 2
},
},
"UpdateInformation": {
"$type": "Asi.Soa.Core.DataContracts.EntityUpdateInformationData, Asi.Contracts",
"CreatedBy": uid,
"CreatedOn": new Date().toISOString(),
"UpdatedBy": uid,
"UpdatedOn": new Date().toISOString()
}
};
return await AVICapiData("/api/cart", cartpost, "POST");
}
async function AVICgetOrCreateCart(uid) {
const result = await AVICapiData(`/api/Cart?UserId=${uid}&UpdatedBy=${uid}`);
cart = null;
if (result["Items"]["$values"].length < 1) {
cart = await AVICcreateCart(uid);
} else {
cart = result["Items"]["$values"][0];
}
return cart;
}
async function AVICchangeBillToOrg(uid, order) {
// get user info, OrgID
const user = await AVICapiData(`/api/Person/${uid}`);
var oid = user["PrimaryOrganization"]["OrganizationPartyId"];
if (oid == undefined) { return order; }
order["BillToCustomerParty"]["PartyId"] = oid;
order = await AVICapiData("/api/Order/_execute", {
"$type": "Asi.Soa.Commerce.DataContracts.OrderPriceUpdateRequest, Asi.Contracts",
"EntityTypeName": "Order",
"OperationName": "UpdatePricing",
"Order": order
}, "POST");
return order;
}
async function AVICaddToCart(productID) {
const uid = JSON.parse(document.getElementById("__ClientContext").value)["loggedInPartyId"];
// get cart
var cart = await AVICgetOrCreateCart(uid);
// get item
const itemresult = await AVICapiData(`/api/ItemSummary/${productID}`);
var order = cart["ComboOrder"]["Order"];
// append to order
const orderlines = order["Lines"]["$values"].length;
order["Lines"]["$values"].push(createOrderLine(itemresult, orderlines+1));
// update pricing
order = await AVICapiData("/api/Order/_execute", {
"$type": "Asi.Soa.Commerce.DataContracts.OrderPriceUpdateRequest, Asi.Contracts",
"EntityTypeName": "Order",
"OperationName": "UpdatePricing",
"Order": order
}, "POST");
//post... again, since the first post doesn't get correct pricing.
order = await AVICapiData("/api/Order/_execute", {
"$type": "Asi.Soa.Commerce.DataContracts.OrderPriceUpdateRequest, Asi.Contracts",
"EntityTypeName": "Order",
"OperationName": "UpdatePricing",
"Order": order
}, "POST");
// replace order data in cart with above
cart["ComboOrder"]["Order"] = order;
await AVICapiData(`/api/cart/${cart["CartId"]}`, cart, "PUT");
// get updated cart to attempt to change billto orgid
cart = await AVICgetOrCreateCart(uid);
order = cart["ComboOrder"]["Order"];
order = await AVICchangeBillToOrg(uid, order); // change bill to user to bill to org
// replace order data in cart with above
cart["ComboOrder"]["Order"] = order;
await AVICapiData(`/api/cart/${cart["CartId"]}`, cart, "PUT");
}
Just a note on the above - it doesn't purge/delete any existing cart so if you want to reset your state, you may want to delete your cart by calling this helper function (you will get an error because it doesn't return any JSON response and I don't sanity check that):
async function AVICpurgeCart() {
const uid = JSON.parse(document.getElementById("__ClientContext").value)["loggedInPartyId"];
const result = await AVICapiData(`/api/Cart?UserId=${uid}&UpdatedBy=${uid}`);
if (result["Items"]["$values"].length > 0) {
await AVICapiData(`/api/cart/${result["Items"]["$values"][0]["CartId"] }`, null, "DELETE");
}
}
// await AVICpurgeCart(); to purge existing cart for the currently logged in user.
The full snippet including the above helper function:
async function AVICapiData(endpoint, data=null, method="GET") {
var opts = {
method: method,
headers: {
"Content-Type": "application/json",
"RequestVerificationToken": document.getElementById("__RequestVerificationToken").value
}
}
if (data != null) { opts["body"] = JSON.stringify(data); }
const response = await fetch(endpoint, opts);
return await response.json();
}
function createOrderLine(itemData, lineno) {
return {
"$type": "Asi.Soa.Commerce.DataContracts.OrderLineData, Asi.Contracts",
"OrderLineId": self.crypto.randomUUID(),
"Item": itemData,
"QuantityOrdered": {
"$type": "System.Nullable`1[[Asi.Soa.Commerce.DataContracts.QuantityData, Asi.Contracts]], mscorlib",
"Amount": 1
},
"LineNumber": lineno,
"SourceCode": "",
"CanCombine": true,
"UsesPriceGroup" : true
}
}
async function AVICcreateCart(uid) {
const cartpost = {
"$type": "Asi.Soa.Commerce.DataContracts.CartData, Asi.Contracts",
"UserId": uid,
"ComboOrder": {
"$type": "Asi.Soa.Commerce.DataContracts.ComboOrderData, Asi.Contracts",
"Order": {
"$type": "Asi.Soa.Commerce.DataContracts.OrderData, Asi.Contracts",
"Lines": {
"$type": "Asi.Soa.Commerce.DataContracts.OrderLineDataCollection, Asi.Contracts",
"$values": []
},
"SoldToCustomerParty": {
"$type": "Asi.Soa.Commerce.DataContracts.CustomerPartyData, Asi.Contracts",
"PartyId": uid
},
"BillToCustomerParty": {
"$type": "Asi.Soa.Commerce.DataContracts.CustomerPartyData, Asi.Contracts",
"PartyId": uid
},
"OriginatorCustomerParty": {
"$type": "Asi.Soa.Commerce.DataContracts.CustomerPartyData, Asi.Contracts",
"PartyId": uid
},
"Currency": {
"$type": "Asi.Soa.Core.DataContracts.CurrencyData, Asi.Contracts",
"CurrencyCode": "AUD",
"DecimalPositions": 2
},
"SourceCode": ""
},
"Currency": {
"$type": "Asi.Soa.Core.DataContracts.CurrencyData, Asi.Contracts",
"CurrencyCode": "AUD",
"DecimalPositions": 2
},
},
"UpdateInformation": {
"$type": "Asi.Soa.Core.DataContracts.EntityUpdateInformationData, Asi.Contracts",
"CreatedBy": uid,
"CreatedOn": new Date().toISOString(),
"UpdatedBy": uid,
"UpdatedOn": new Date().toISOString()
}
};
return await AVICapiData("/api/cart", cartpost, "POST");
}
async function AVICgetOrCreateCart(uid) {
const result = await AVICapiData(`/api/Cart?UserId=${uid}&UpdatedBy=${uid}`);
cart = null;
if (result["Items"]["$values"].length < 1) {
cart = await AVICcreateCart(uid);
} else {
cart = result["Items"]["$values"][0];
}
return cart;
}
async function AVICchangeBillToOrg(uid, order) {
// get user info, OrgID
const user = await AVICapiData(`/api/Person/${uid}`);
var oid = user["PrimaryOrganization"]["OrganizationPartyId"];
if (oid == undefined) { return order; }
order["BillToCustomerParty"]["PartyId"] = oid;
order = await AVICapiData("/api/Order/_execute", {
"$type": "Asi.Soa.Commerce.DataContracts.OrderPriceUpdateRequest, Asi.Contracts",
"EntityTypeName": "Order",
"OperationName": "UpdatePricing",
"Order": order
}, "POST");
return order;
}
async function AVICpurgeCart() {
const uid = JSON.parse(document.getElementById("__ClientContext").value)["loggedInPartyId"];
const result = await AVICapiData(`/api/Cart?UserId=${uid}&UpdatedBy=${uid}`);
if (result["Items"]["$values"].length > 0) {
await AVICapiData(`/api/cart/${result["Items"]["$values"][0]["CartId"] }`, null, "DELETE");
}
}
async function AVICaddToCart(productID) {
const uid = JSON.parse(document.getElementById("__ClientContext").value)["loggedInPartyId"];
// get cart
var cart = await AVICgetOrCreateCart(uid);
// get item
const itemresult = await AVICapiData(`/api/ItemSummary/${productID}`);
var order = cart["ComboOrder"]["Order"];
// append to order
const orderlines = order["Lines"]["$values"].length;
order["Lines"]["$values"].push(createOrderLine(itemresult, orderlines+1));
// update pricing
order = await AVICapiData("/api/Order/_execute", {
"$type": "Asi.Soa.Commerce.DataContracts.OrderPriceUpdateRequest, Asi.Contracts",
"EntityTypeName": "Order",
"OperationName": "UpdatePricing",
"Order": order
}, "POST");
//post... again, since the first post doesn't get correct pricing.
order = await AVICapiData("/api/Order/_execute", {
"$type": "Asi.Soa.Commerce.DataContracts.OrderPriceUpdateRequest, Asi.Contracts",
"EntityTypeName": "Order",
"OperationName": "UpdatePricing",
"Order": order
}, "POST");
// replace order data in cart with above
cart["ComboOrder"]["Order"] = order;
await AVICapiData(`/api/cart/${cart["CartId"]}`, cart, "PUT");
// get updated cart to attempt to change billto orgid
cart = await AVICgetOrCreateCart(uid);
order = cart["ComboOrder"]["Order"];
order = await AVICchangeBillToOrg(uid, order); // change bill to user to bill to org
// replace order data in cart with above
cart["ComboOrder"]["Order"] = order;
await AVICapiData(`/api/cart/${cart["CartId"]}`, cart, "PUT");
}
Hi Lee,
I'm starting to look into this. The first thing I verified is that everyone should have permission to execute on the Order endpoint so it's likely bumping into a permission error when trying to access something in the order like the ship to contact or the bill to contact. Are you able read both contacts using the same login you are using on the pricing request?
Did tech support look into error logs for you? If you can repeat the steps and let me know what time you received the errors I can try to dig and see if we have more meaningful errors buried somewhere.
Thanks,
Courtney
Hi Courtney,
Reading both contacts - Not sure what both means here. Do you mean "self" the person adding to cart and the "bill to" ID (the organisation)? If so, yes they are able to be read just fine. I am able to visit /iCore/Contacts/OrganizationLayouts/Organization_Profile.aspx?ID=37288
, and obviously my own contact. I'm also able to read both contacts via the API:
The issue I mentioned was the reason behind starting this endeavour. It wasn't about this particular issue. I did however raise another support ticket about this issue which I think prompted your response here. So no, no one has looked in to logs.
I ran the above most recent javascript block, and then the function await AVICaddToCart("MPAC");
which generated the error on UpdatePricing (the above most recent block attempts to change the billto ID after getting correct pricing for individual first):
just now at Jan 18 20:27:38
Thank you for looking in to this for me.
Hi Lee,
Thanks for reproducing it. I was able to retrieve the error from the logs and can confirm that it appears to be a permission problem accessing the bill to contact. Unfortunately, I cannot see exactly what bill to ID it was trying to use.
Here it the path that it's following:
Recalculate Line Amounts -> Get the Pricing Group Price -> /api/PartyItemPrice?ItemId=[ItemCode]&PartyId=BillToPartyId&ItemClass=SALES
In the PartyItemPrice find, it is trying to do a get on the Party endpoint: api/Party/[BillToPartyId].
Is it possible that you have an extra space or something in the bill to ID? I'd suggest replicating adding a product to the cart via the UI, setting the bill via the payment creator, and then doing a Get on the Cart endpoint to understand the difference.
BTW - I looked into ZD 267095 and it appears to be the same issue as this one here: https://support.imis.com/hc/en-us/articles/15741445605261-95171-ZD-248267-View-Cart-on-Product-Display-Issue
The problem seems to be that the link for "View Cart" is missing a reference to the current website, either via URL path or a WebsiteKey URL parameter. Because of this, I think it's redirecting to the default website which may be a site that public users don't have access to (the out of the box default site is the Staff site). I bet with some Javascript on that page, all "View Cart" links could be modified to include "?WebsiteKey=" + gWebsiteKey. (gWebsiteKey is a global JavaScript variable built into iMIS and should always be populated.)
I'm happy to help more if I can. If this doesn't provide any insight, then some concrete payloads examples with the exact JSON you are using and the JSON that iMIS will build by default would help.
Courtney
Hiya,
Thanks for looking in to that.
- Extra space?
You can see the code above. All I do is take the org ID from the contact card and put it in the order data structure:
var oid = user["PrimaryOrganization"]["OrganizationPartyId"];
order["BillToCustomerParty"]["PartyId"] = oid;
- Inspect the cart
Yes, I have stared at the UI cart and tried to generate order data structures to replicate that. Do note, because I cannot see the UpdatePricing calls done internally within the UI I cannot know what order of calls they are making nor the data structure. At this point I'm basically begging for someone to tell me what iMIS is doing behind the scenes because there is no way for me to see and the documentation (of course) does not go in to any detail about the nuances of UpdatePricing, nor explain the full call chain.
The most important point is... I cannot actually generate a valid cart because the steps leading up to the cart generation fail (UpdatePricing). It was only through trial and error that I guessed I had to call UpdatePricing twice, and from what I heard from ASI staff looking at the Insights data, it seems that the iMIS UI is also calling UpdatePricing twice. No one would know to do that though because the documentation doesn't say anything.
- ZD 248267
Not sure what this has to do with my problem nor 267095.
i. In 267095 I have done all sorts of testing that do not involve clicking on the "view cart" link and instead have the cart manually open in a different tab. (More importantly 267095 describes how ProductDisplayList and ItemDetail "Add to cart" behave differently and one generates a broken cart and the other does not)
ii. For this issue, it's the same. I can sit on the actual cart page and run the javascript blocks mentioned above and still get the same errors.
This is a frustrating response. I have given a fully self-contained simple to understand javascript block that replicates the issue. I have also asked what the UI does behind the scenes so I can simply copy it.
It's frustrating for two reasons:
- It is obvious that there is an issue or nuance to calling UpdatePricing, but no one seems to acknowledge it
- No one will tell me how to actually do it how the UI does it.
I don't understand why you want concrete JSON payloads because you can simply run the javascript block above and inspect any payload you like at any point. I've given you everything and all you need to do is look at and run the code and you can see it for yourself. Regardless I have posted .har files in ticket 268994, but I really wish you (or someone) would run and play with the example code yourself to experience it in person.
Attempt1.har - This creates a cart with bill to current user's org, then attempts to add the item to the order and update pricing.
Attempt2.har - This is attempting to first setup an ordinary cart that bills to current user, then after adding the item to the cart then attempts to change the order to bill to org and then update pricing.
Just to reiterate, our environment is:
- Settings -> Contacts -> General -> Users who can bill to their organisation: All users - organization selected by default
- Add Pricing Group on the item -> Add new pricing group -> Group Type -> Member Type
Thank you.
Hi Lee,
I'm sorry that you are feeling frustrated. I would be too.
I want to assure you that I spent all day researching this issue and the one that initially led you down this path (ZD 267095). I was hopeful that if we could discover what caused that issue then you could go back to an out of the box solution. When investigating ZD 267095, I saw a recording of Paul reproducing what he thought was the same issue you encountered. However, this recording was actually reproducing 248267 which is why I tried to offer a work around for that issue. I realize now that they are not the same issue at all.
The trouble we are having is that no one seems to be able to reproduce the actual issue you are seeing in a demo database, even when using your same setup:
- Settings -> Contacts -> General -> Users who can bill to their organisation: All users - organization selected by default
- Add Pricing Group on the item -> Add new pricing group -> Group Type -> Member Type
- Use this same pricing group on 2 products
- Add both products to the cart
We've tried this with the Product List Display as well as the General Product Display iParts, but "Add to cart" works every time and never gives us the 0.00 price. And likewise, your JavaScript works beautifully in our demo database.
I feel like there is something very specific to your data that is triggering the defect. And it is likely the same underlying problem that iMIS is hitting in ZD 267095.
Thank you for providing the har files. We are reopening ZD 267095 and its associated escalation because it looks like the issue you are seeing still has not been reproduced outside of your iMIS system.
I'll make a note in the ticket that with the error log I gathered yesterday when you reproduced this issue. I'm hopeful that we can find a cause and work around.
Courtney
Hi Courtney,
Thank you for that information. I had not known that this issue had not been reproducible elsewhere. If I had of known, I would have been more understanding.
How do I go about resolving the issue on our tenant? What actions do I need to take next to resolve this?
Thank you for your time and information.
Hi Lee,
No worries. It looks like we thought that we could reproduce the issue which is definitely where all of the confusion started.
No action is needed on your part at the moment. The original ticket and its associated escalation have been re-opened and the developer who originally looked into the issue will pick it back up again. We are going to add some extra logging and reproduce it on a copy of your iMIS system. All of the information we gathered here should help quite a bit and I have copied over the relevant details to that original ticket.
Thank you so much for all of your detailed information and your patience. I will update this post if we are able to find a cause and/or work around.
Courtney
Hi Lee,
It looks like we found the cause of this issue and it is the same underlying issue you reported in ZD 267095. It specifically has to do with products priced by pricing group when "Users who can bill to their organisation" is set to "All users - organization selected by default"
There are 2 bits of good news with this:
- It looks like it has already been fixed as part of another reported defect in the next release (ZD 268706). This is why I wasn't able to reproduce it.
- I think we can make a small configuration change on your iMIS system to get past the issue until it is upgraded to the next release. Your ticket is currently in cloud service's hands to apply this change after hours.
The underlying issue is that although your contact has permission to read their organisation record via the Party endpoint, a GET for the same ID on the PartySummary endpoint will result in a permission error. These two endpoints should have the exact same permissions rules, but it appears that PartySummary was missing the rule to allow users to be able to access any of their available bill to contacts.
Thank you for your persistence on this issue. I've got my fingers crossed that our configuration change will finally resolve it for you.
Courtney
Hi Courtney,
Thank you for the information.
- Part of my issue in 267095 is that ProductDisplayList iPart "add to cart button" and ItemDetail iPart "add to cart button" gave different results. (ItemDetail working and ProductDisplayList did not work)
- Does this fix make both "add to cart buttons" operate the same now? Was one using Party and the other using PartySummary?
- I'm making some assumptions here so please correct me if I am wrong: am I to assume the reason this fix works is because Order/_execute UpdatePricing calls PartySummary behind the scenes?
Thank you again for the information and assistance.
Hi Lee,
From what I can tell, the two add to cart buttons roughly have the same functionality. In the end, they should both end up calling the Order/_execute UpdatePricing method which is indeed where the error is happening. It just might be that one iPart hides the error and the other one makes it more obvious that something went wrong. The other symptom of this is when second item is showing a price of 0.00. This is because iMIS hit an error when it was trying to set the price to something other than 0.00 and it didn't recover well. I believe that changing the quantity in the cart and clicking the "Update" button will cause the same error as well.
You are correct in your assumption that UpdatePricing sometimes calls PartySummary behind the scenes. Specifically, it calls this when the product it is pricing has a pricing group associated with it.
I believe that our configuration change will fix all of the issues you reported: the Order/_execute UpdatePricing call, the Add to Cart button, and the 0.00 price in the cart. I'll follow along in the ZD ticket from here on out to see the final results.
Take care,
Courtney
Hi Courtney,
Thank you for the clarifications. Here's hoping, however I have some reservations regarding 1. because it wasn't just that it "hides the error", one always works (ItemDetail), and the other never works (ProductDisplayList). I guess I'll find out when the update happens.
Thank you again for the extra information.
ο»Ώ