// Implementation of collect data method. Executes after plug-in payment item is added to the order on payment page or on preliminary payments page.
        // To do operations with order that is currently edited by operator, we need special operationService. Do NOT use it after method returns.
        public void OnPaymentAdded(IOrder order, IPaymentItem paymentItem, [NotNull] IUser cashier, [NotNull] IOperationService operations, IReceiptPrinter printer, IViewManager viewManager,
                                   IPaymentDataContext context)
        {
            switch (order.Status)
            {
            case OrderStatus.New:
                // let's add a gift product to the first guest
                var credentials = operations.GetCredentials();

                var guest   = order.Guests.First();                  // lucky guest
                var product = operations.GetActiveProducts().Last(); // gift product
                operations.AddOrderProductItem(3m, product, order, guest, null, credentials);
                var orderWithGift = operations.GetOrderById(order.Id);

                //we assume our gift product is payed by our payment, so automatically add its price to payment sum.
                var giftSum = orderWithGift.ResultSum - order.ResultSum;
                paymentItem = orderWithGift.Payments.Single(p => p.Id == paymentItem.Id);
                operations.ChangePaymentItemSum(paymentItem.Sum + giftSum, giftSum, null, paymentItem, orderWithGift, credentials);
                return;

            case OrderStatus.Bill:
                // we cannot edit order widely after bill, but at least we can set possible sum range and provide initial sum value
                operations.ChangePaymentItemSum(42m, 0m, 100500m, paymentItem, order, operations.GetCredentials());
                return;

            default:
                // we don't expect payment item to be added in statuses other than new and bill
                throw new ArgumentOutOfRangeException();
            }
        }