private void Clover_LogSale(long amount, DateTime date, string externalId, SaleResponse response)
 {
     // Clover notifications happen on background threads, invoke a call on the ui thread
     if (InvokeRequired)
     {
         BeginInvoke((Action <long, DateTime, string, SaleResponse>)Clover_LogSale, amount, date, externalId, response);
     }
     else
     {
         Log.AddItem(date, SaleKeypadControl.BuildDisplayString(amount.ToString()), externalId, response?.Payment?.id ?? "", response?.Success ?? false, response?.Payment?.cardTransaction?.last4 ?? "");
     }
 }
        /// <summary>
        /// Sale completed on the clover device
        /// </summary>
        /// <param name="success"></param>
        /// <param name="details"></param>
        private void Clover_SaleComplete(bool success, SaleResponse details)
        {
            // Clover notifications happen on background threads, invoke a call on the ui thread
            if (InvokeRequired)
            {
                BeginInvoke((Action <bool, SaleResponse>)Clover_SaleComplete, success, details);
            }
            else
            {
                if (success)
                {
                    SaleKeypadControl.NewSale();

                    MessageBox.Show(this, $"Sale completed {details.Result} \"{details.Reason}\"\n{details.Message}\nid = {details.Payment.id}, external id = {details.Payment.externalPaymentId}", $"Sale {(success ? "Complete" : "Failed")}", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
                else
                {
                    MessageBox.Show(this, $"Sale Completed with results: {details.Result} \"{details.Reason}\"\n{details.Message}", $"Sale Failed", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                }
                Debug.WriteLine($"Sale completed. success={success}, message=\"{details.Message ?? ""}\"");
            }
        }