Page 1 of 1

SalesOrderLine updating QuantityOrdered

PostPosted: Fri Jan 15, 2021 10:44 am
by neil.interactit
Hi guys,

I have built many watchers that add SOEs no probs. I have a new requirement that involves updating the quantity of existing sales order lines. This seemed trivial, but I'm getting "duplicate index" errors.

Code snippet is:

Code: Select all
                        var salesOrderLine = (from SalesOrderLine line in salesOrder.SalesOrderLines select line).FirstOrDefault(x => x.Description == description && x.PriceIncGST == price);
                        if (salesOrderLine == null) continue;
                        salesOrderLine.QuantityOrdered = newQuantity;
                        salesOrder.Save();

I've spent the last week on and off making various little changes, but can't get this to work robustly.

Any and all advice appreciated.

Cheers,
Neil

Re: SalesOrderLine updating QuantityOrdered

PostPosted: Fri Jan 15, 2021 11:34 am
by SBarnes
I would suggest you only use a salesorder object and call save on that as the line is designed to be part of a collection and when the entire sales order object is saved a transaction is started and committed for the entire lot.

There are also properties in the so_main and or so_history that need to get updated as well.

Given the change and insert flags on the lines only the changed one will run an update sql anyway.

Re: SalesOrderLine updating QuantityOrdered

PostPosted: Fri Jan 15, 2021 4:06 pm
by neil.interactit
Hi Stuart, I have updated the code snippet in the first post to reflect your suggested change.

This still seems to produce the same error:
Code: Select all
{
    "ResponseStatus": {
        "ErrorCode": "ConcurrencyConflictException",
        "Message": "Unable to update table SO_Main with InvoiceNo [214189], InvoiceID [c0f4e56700f94b82a3e8]",
        "Errors": []
    }
}

Re: SalesOrderLine updating QuantityOrdered

PostPosted: Fri Jan 15, 2021 4:08 pm
by SBarnes
Can you post the entire code?

Re: SalesOrderLine updating QuantityOrdered

PostPosted: Mon Jan 18, 2021 8:27 am
by neil.interactit
Sure.

This is a custom API response. The "Non-MAIB" code (which just adds without updating) works fine, it's the "MAIB" code producing the error above ...

Code: Select all
        [Authenticate]
        public SalesOrderLinesResponse Post(SalesOrderLinesRequest request)
        {
            var manager = this.SessionAs<JiwaFinancials.Jiwa.JiwaServiceModel.JiwaAuthUserSession>().Manager;
            var pendingOrders = GetPendingOrders(manager);
            var response = new SalesOrderLinesResponse();
            foreach (var orderLine in request.SalesOrderLines.OrderBy(x => x.DebtorCode).ThenBy(x => x.Reference).ToArray())
            {
                var errors = new List<string>();
                // Parameter validation trimmed for clarity
                string invoiceNo = null;
                if (!errors.Any() && debtorRec != null)
                {
                    if (orderLine.DebtorCode == "MAIB")
                    {
                        var wrapper = pendingOrders.FirstOrDefault(x => x.DebtorID == debtorRec.DebtorID && x.ClientNameMatch(orderLine.ClientName) && x.ClaimNumberMatch(orderLine.ClaimNumber) && x.EndDate == orderLine.EndDate && x.DescriptionMatch(orderLine.Description));
                        if (wrapper == null) { wrapper = new SalesOrderWrapper(CreateNewSalesOrder(manager, debtorRec.DebtorID, orderLine)); pendingOrders.Add(wrapper); }
                        invoiceNo = wrapper.SalesOrder.InvoiceNo;
                        var price = orderLine.UnitPrice ?? 0;
                        if (orderLine.Gst ?? false) price = Math.Round(price * 1.1m, 2);
                        var salesOrderLine = (from SalesOrderLine line in wrapper.SalesOrder.SalesOrderLines select line).FirstOrDefault(x => x.Description.Contains(" - Week " + orderLine.WeekNo + " - ") && x.PriceIncGST == price);
                        if (salesOrderLine == null) AddMaibSalesOrderLines(manager, orderLine, wrapper.SalesOrder);
                        wrapper.SalesOrder.Read(wrapper.SalesOrder.InvoiceID);
                        salesOrderLine = (from SalesOrderLine line in wrapper.SalesOrder.SalesOrderLines select line).FirstOrDefault(x => x.Description.Contains(" - Week " + orderLine.WeekNo + " - ") && x.PriceIncGST == price);
                        if (salesOrderLine == null) { errors.Add("Untrapped error: Cannot find 'Week " + orderLine.WeekNo + "', Price:" + price + " in MAIB sales order " + wrapper.SalesOrder.OrderNo); continue; }
                        salesOrderLine.QuantityOrdered += orderLine.Quantity ?? 0;
                        wrapper.SalesOrder.Save();
                    }
                    else
                    {
                        var wrapper = pendingOrders.FirstOrDefault(x => x.DebtorID == debtorRec.DebtorID && x.Reference == orderLine.Reference);
                        if (wrapper == null) { wrapper = new SalesOrderWrapper(CreateNewSalesOrder(manager, debtorRec.DebtorID, orderLine)); pendingOrders.Add(wrapper); }
                        invoiceNo = wrapper.SalesOrder.InvoiceNo;
                        var error = AddSalesOrderLine(manager, orderLine, wrapper.SalesOrder);
                        if (error != null) errors.Add(error);
                    }
                }
                response.SalesOrderLines.Add(new SalesOrderLineResponse(orderLine, invoiceNo, errors));
            }
            return response;
        }

I should also add, that I'm seeing a SOE with the qty of one of the lines updated once ... so it seems the code works on the first iteration, but when the same salesOrderLine is re-processed to further amend the qty, it fails.

Note that I can't pre-process these quantities and then just add a SOE with final quantities, as this process (amending the quantities) occurs over multiple API transactions over time.

Cheers,
Neil

Re: SalesOrderLine updating QuantityOrdered  Topic is solved

PostPosted: Mon Jan 18, 2021 9:35 am
by SBarnes
The error you are getting is directly produced from the iSave procedure in the Sales Order failing when executed against the database, in other words the save call is failing, when you say things are working on the first use of the sales order but not subsequent ones I suspect what you need to do after saving the order is to read it back in by doing the following:


Code: Select all
 wrapper.SalesOrder.Save();
 wrapper.SalesOrder.Read(wrapper.SalesOrder.InvoiceID);

Re: SalesOrderLine updating QuantityOrdered

PostPosted: Mon Jan 18, 2021 10:55 am
by neil.interactit
Nailed it! Many thanks Stuart!

The only tweak was that the Read() was required before the Save().

In case others wind up here, I have edited and updated the "entire code" clip above to show the final working solution.

Thanks again,
Neil

Re: SalesOrderLine updating QuantityOrdered

PostPosted: Mon Jan 18, 2021 5:11 pm
by pricerc
I have got into the habit of (re-)Read()ing any object that I Save(), as the very next method call, if I'm expecting to use the object again.

It would be nice if Save() left objects in a completely consistent state, but it doesn't, and I wouldn't want it changed, as the overhead of re-reading all that data isn't always necessary.