The Order Payment Screen (Checkout Screen) Allows Changes Initiated by the Plugin
Starting from V9Preview3, the plugin can edit the current order opened at the checkout via the API without receiving
EntityAlreadyInUseException :-)
Previously, in V7Preview5, the ability to edit an open order on the editing screen was added at any time when no other operations were being performed (details).
To make changes to the order opened on the payment screen, the plugin needs to call the method
TryEditCurrentPaymentScreen
and pass a reference to a callback that SyrveFront will invoke as soon as it becomes possible.
If idle, this will happen immediately, but if other operations are being performed at that moment, the callback will be invoked right after their completion.
In any case, the TryEditCurrentPaymentScreen method will return control after the callback is invoked.
If the callback throws an exception, it will be thrown from TryEditCurrentPaymentScreen.
If another operation was being performed at the time of calling TryEditCurrentPaymentScreen, which ultimately led to exiting the order payment screen,
the callback will not be invoked either immediately or deferred, and the TryEditCurrentPaymentScreen method will generate an OperationCanceledException.
During the execution of the callback, a progress bar is displayed. The following will be passed to the callback:
- the current order,
- context about the state of the checkout screen
IPaymentScreenUpdatedContext, - a local version of
IOperationServicefor editing the current order, IViewManagerwith the ability to show dialog windows and change text on the progress bar.
The callback has a return value, which should be null for most users.
Example:
private void EditPayScreen()
{
PluginContext.Operations.TryEditCurrentPaymentScreen(x =>
{
// In the price-splitting mode (currently unavailable for most users), we add a new guest to the order,
// subtracting 10 from the existing guests' resulting sums and adding it to the new guest.
if (x.context.PaymentSplitMode == PaymentSplitMode.SplitByPrice)
{
var guestsSums = new List<(Guid, decimal)>();
var newGuest = x.os.AddOrderGuest($"Guest {x.context.PaymentSplitGuestInfos.Count + 1}", x.order, x.os.GetDefaultCredentials());
var newGuestResultSum = 0m;
foreach (var guestInfo in x.context.PaymentSplitGuestInfos)
{
if (guestInfo.ResultSum > 10)
{
guestsSums.Add((guestInfo.GuestId.Value, guestInfo.ResultSum - 10));
newGuestResultSum += 10;
}
else
{
guestsSums.Add((guestInfo.GuestId.Value, guestInfo.ResultSum));
}
}
guestsSums.Add((newGuest.Id, newGuestResultSum));
// Returning the distribution of sums among guests in price-splitting mode.
return guestsSums;
}
// In the dish-splitting mode (currently unavailable for most users), we add a new dish to the last guest.
if (x.context.PaymentSplitMode == PaymentSplitMode.SplitByDish)
{
var product = x.os.GetActiveProducts().Single(p => p.Name == "Promotional Dish");
x.os.AddOrderProductItem(1m, product, x.order, x.order.Guests.Last(), null, x.os.GetDefaultCredentials());
// Returning null, as the distribution of sums among guests in dish-splitting mode is unavailable.
return null;
}
// In the whole order mode (default), we add a payment of type VISA for the full amount to the order.
if (x.context.PaymentSplitMode == PaymentSplitMode.WholeOrder)
{
x.os.AddPaymentItem(x.context.PaymentSplitGuestInfos.Single().ResultSum, null, x.os.GetPaymentTypes().First(p => p.Name.ToUpper() == "VISA"), x.order, x.os.GetDefaultCredentials());
// Returning null, as the distribution of sums among guests in whole order mode is unavailable.
return null;
}
throw new InvalidEnumArgumentException(nameof(x.context.PaymentSplitMode), (int)x.context.PaymentSplitMode, typeof(PaymentSplitMode));
});
}