Place order from code with custom price

We’re placing orders from code using the example code from here, Create order from code (Litium 8) - Questions - Litium Forum and everything works fine.
However, sometimes we need to set a custom price on the order row. How can we do that?

Tried doing it like this but it throws an error saying the object is read only.

var orderRow = cartContext.Cart.Order.Rows.FirstOrDefault();
orderRow.VatRate = 1 - (cartContext.Cart.Order.GrandTotal / paidAmount);
orderRow.TotalExcludingVat = _roundOffService.Round(currency.Id, orderRow.UnitPriceExcludingVat * orderRow.Quantity);
orderRow.TotalIncludingVat = _roundOffService.Round(currency.Id, orderRow.TotalExcludingVat * (1 + orderRow.VatRate));
orderRow.UnitPriceIncludingVat = _roundOffService.Round(currency.Id, orderRow.TotalIncludingVat / orderRow.Quantity);
orderRow.TotalVat = orderRow.TotalIncludingVat - orderRow.TotalExcludingVat;
orderRow.VatDetails = [new VatDetail { VatRate = orderRow.VatRate, AmountIncludingVat = orderRow.TotalIncludingVat, Vat = orderRow.TotalVat }];

Also tried to make a writable clone of the cartContext.Cart.Order, do the changes and then put the order back, but we get the same error then.

Litium version: 8.20.3

Ok, so after some consulting with Litium support it seems there’s, as of now, no easy way to do this. In our case the customer has already paid so we just need to push an order thru using the direct payment. The, not so pretty, solution we came up with is to place the order with the list price and then listen for the SalesOrderConfirmed event and do the price modifications there. Changes need to be done on the order row, payment and transactions. If a shipment has been created the shipment rows needs to be changed as well.

Our current case is pretty simple as it just has one order row. The case is for a customer that has paid list price + US sales tax. When creating the order we add additional info on the order row of the amount the customer paid. We then do the assumption that the difference between the paid amount and the amount on the order row is sales tax and go from there.

_eventBroker.Subscribe<SalesOrderConfirmed>(x =>
{
    var orderOverview = _orderOverviewService.Get(x.Item.SystemId);
    var salesOrder = orderOverview.SalesOrder.MakeWritableClone();

    try
    {
        var orderRow = salesOrder.Rows.FirstOrDefault();
        var paidAmount = Convert.ToDecimal(orderRow?.AdditionalInfo?.FirstOrDefault(a => a.Key.Equals(AdditionalInfoConstants.FlowSubscriptionPaidAmount, StringComparison.InvariantCultureIgnoreCase)).Value ?? 0);

        var vatRate = (paidAmount / salesOrder.GrandTotal) - 1;
        var totalExcludingVat = _roundOffService.Round(salesOrder.CurrencyCode, orderRow.UnitPriceExcludingVat * orderRow.Quantity);
        var totalIncludingVat = _roundOffService.Round(salesOrder.CurrencyCode, totalExcludingVat * (1 + vatRate));
        var unitPriceIncludingVat = _roundOffService.Round(salesOrder.CurrencyCode, totalIncludingVat / orderRow.Quantity);
        var totalVat = totalIncludingVat - totalExcludingVat;
        var vatDetails = new VatDetail { VatRate = vatRate, AmountIncludingVat = totalIncludingVat, Vat = totalVat };

        // Paid amount contains sales tax - add it to the order row
        orderRow.VatRate = vatRate;
        orderRow.TotalExcludingVat = totalExcludingVat;
        orderRow.TotalIncludingVat = totalIncludingVat;
        orderRow.UnitPriceIncludingVat = unitPriceIncludingVat;
        orderRow.TotalVat = totalVat;
        orderRow.VatDetails = [vatDetails];

        using (_securityContextService.ActAsSystem())
        {
            _orderService.Update(salesOrder);
        }

        var writablePayment = _paymentService.Get(salesOrder.OrderPaymentLinks.FirstOrDefault().PaymentSystemId).MakeWritableClone();
        writablePayment.TotalAmountExcludingVat = totalExcludingVat;
        writablePayment.TotalAmountIncludingVat = totalIncludingVat;
        writablePayment.TotalVat = totalVat;

        using (_securityContextService.ActAsSystem())
        {
            _paymentService.Update(writablePayment);
        }

        foreach (var transaction in _transactionService.GetByPayment(writablePayment.SystemId))
        {
            var writableTransaction = transaction.MakeWritableClone();
            foreach (var transactionRow in writableTransaction.Rows)
            {
                transactionRow.VatRate = vatRate;
                transactionRow.TotalExcludingVat = totalExcludingVat;
                transactionRow.TotalIncludingVat = totalIncludingVat;
                transactionRow.UnitPriceIncludingVat = unitPriceIncludingVat;
                transactionRow.TotalVat = totalVat;
                transactionRow.VatDetails = [vatDetails];
            }

            using (_securityContextService.ActAsSystem())
            {
                _transactionService.Update(writableTransaction);
            }
        }
    }
    catch (Exception e)
    {
        // Log error
    }
});

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.