Zwroty produktów i zamówień z zamkniętych zmian kasowych
Teraz możliwe jest zwracanie produktów lub zamówień z zamkniętych zmian kasowych nie tylko z UI SyrvePOS, ale także z API V8.
W jednej z poprzednich wiadomości
mówiliśmy o sposobach pobierania zamówień z zamkniętych zmian kasowych.
Teraz, jeśli zajdzie taka potrzeba, możesz dostosować listę dań takiego zamówienia i zwrócić je, wywołując metodę
StornoPastOrder.
Jeśli potrzebujesz zwrócić towary, które nie są powiązane z konkretnym zamówieniem, możesz użyć metody
StornoPastOrderItems,
wcześniej generując listę towarów items do zwrotu.
PastOrderItem.Price oraz
PastOrderItem.SumWithoutDiscounts
nie są używane; można je pozostawić puste podczas przekazywania do metody.
Możesz również określić z API rozmiar dania, jeśli jest on obsługiwany.
Każdy z przekazanych items może być oznaczony jako modyfikator lub danie główne
(PastOrderItem.IsMainDish).
Podobnie jak w UI i bez ścisłych kontroli zgodności z typem pozycji z karty.
Jednak modyfikator nie może być pierwszym elementem listy.
Ponadto danie oznaczone jako modyfikator nie może mieć rozmiaru.
Każdy PastOrderItem
musi wskazywać miejsce przygotowania oraz typ miejsca przygotowania.
Obecnie zwrot jest możliwy tylko na domyślnym rejestratorze fiskalnym bieżącego terminala.
Zmiana kasowa musi być otwarta i musi być wystarczająca ilość gotówki na zwroty gotówkowe.
Typ płatności do storna można uzyskać za pomocą
GetPaymentTypesToStornoPastOrderItems.
Możesz także zwrócić typ płatności wtyczki
(z zaznaczeniem canProcessPaymentReturnWithoutOrder równym true, przekazywanym do
RegisterPaymentSystem).
Typ usunięcia do storna można uzyskać za pomocą
GetRemovalTypesToStornoPastOrderItems.
Typ usunięcia może być
- bez odpisu
(IRemovalType.WriteoffType== WriteoffType.None) - z odpisem
(IRemovalType.WriteoffType.HasFlag(WriteoffType.Cafe))
Przy storno z odpisem sprawdzana jest obecność niestandardowego typu płatności "Zwrot od klienta".
Oddział musi należeć do bieżącej grupy, a oddział musi posiadać magazyn.
System podatkowy jest przekazywany tylko, jeśli został pobrany przez
GetTaxationSystemsToStornoPastOrderItems.
Przy storno z odpisem sprawdzane jest prawo F_STRN (Zwrot płatności).
Przy storno bez odpisu sprawdzane jest prawo F_SWWOFF (Zwrot płatności na paragon bez zwrotu do magazynu).
Przykłady:
private void StornoPastOrder()
{
var pastOrder = PluginContext.Operations.GetPastOrders().First();
var paymentType = pastOrder.Payments.First();
// rt.WriteoffType.HasFlag(WriteoffType.Cafe) - storno z odpisem
// rt.WriteoffType == WriteoffType.None - storno bez odpisu
var removalType = PluginContext.Operations.GetRemovalTypesToStornoPastOrderItems().First(rt => rt.WriteoffType.HasFlag(WriteoffType.Cafe));
var section = pastOrder.RestaurantSection;
var orderType = pastOrder.OrderType;
var taxationSystem = PluginContext.Operations.GetTaxationSystemsToStornoPastOrderItems().Select(ts => (TaxationSystem?)ts).FirstOrDefault();
PluginContext.Operations.StornoPastOrder(
PluginContext.Operations.GetCredentials(),
pastOrder,
paymentType,
removalType,
section,
orderType,
null,
taxationSystem,
null);
}
private void StornoProducts()
{
var paymentType = PluginContext.Operations.GetPaymentTypesToStornoPastOrderItems().First(pt => pt.Name.Contains("SampleApiPayment"));
// rt.WriteoffType.HasFlag(WriteoffType.Cafe) - storno z odpisem
// rt.WriteoffType == WriteoffType.None - storno bez odpisu
var removalType = PluginContext.Operations.GetRemovalTypesToStornoPastOrderItems().First(rt => rt.WriteoffType.HasFlag(WriteoffType.Cafe));
var section = PluginContext.Operations.GetTerminalsGroupRestaurantSections(PluginContext.Operations.GetHostTerminalsGroup()).First();
var orderType = PluginContext.Operations.GetOrderTypes().FirstOrDefault(ot => ot.OrderServiceType == OrderServiceTypes.Common);
var taxationSystem = PluginContext.Operations.GetTaxationSystemsToStornoPastOrderItems().Select(ts => (TaxationSystem?)ts).FirstOrDefault();
var activeProducts = PluginContext.Operations.GetActiveProducts()
.Where(product => product.Template == null &&
(product.Type == ProductType.Dish || product.Type == ProductType.Modifier || product.Type == ProductType.Goods || product.Type == ProductType.ForPurchase))
.ToList();
PluginContext.Operations.StornoPastOrderItems(
PluginContext.Operations.GetCredentials(),
GetPastOrderItems(activeProducts).ToList(),
paymentType,
removalType,
section,
orderType,
null,
taxationSystem,
null);
}
private IEnumerable<PastOrderItem> GetPastOrderItems(IReadOnlyList<IProduct> activeProducts)
{
var product = activeProducts.First(p => p.Name.Contains("Tea"));
yield return new PastOrderItem
{
IsMainDish = true,
Product = product,
ProductSize = PluginContext.Operations.GetProductSizes().FirstOrDefault(ps => ps.Name.Contains("S")),
Amount = 2,
SumWithDiscounts = 100.5m,
Price = 0, // nieużywane w StornoPastOrderItems
SumWithoutDiscounts = 0, // nieużywane w StornoPastOrderItems
};
product = activeProducts.First(p => p.Name.Contains("Cream"));
yield return new PastOrderItem
{
IsMainDish = false,
Product = product,
ProductSize = null,
Amount = 2,
SumWithDiscounts = 0m,
Price = 0, // nieużywane w StornoPastOrderItems
SumWithoutDiscounts = 0, // nieużywane w StornoPastOrderItems
};
product = activeProducts.First(p => p.Name.Contains("Puree"));
yield return new PastOrderItem
{
IsMainDish = true,
Product = product,
ProductSize = null,
Amount = 1,
SumWithDiscounts = 90m,
Price = 0, // nieużywane w StornoPastOrderItems
SumWithoutDiscounts = 0, // nieużywane w StornoPastOrderItems
};
product = activeProducts.First(p => p.Name.Contains("Bottle"));
yield return new PastOrderItem
{
IsMainDish = true,
Product = product,
ProductSize = null,
Amount = 2,
SumWithDiscounts = -15m,
Price = 0, // nieużywane w StornoPastOrderItems
SumWithoutDiscounts = 0, // nieużywane w StornoPastOrderItems
};
}