adapt money return receipt to new refund payload schema
This commit is contained in:
@@ -463,64 +463,46 @@ public static class TestHelpers
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mirrors money_return_receipt_data.json plus the credit-note specific fields
|
// Mirrors money_return_receipt_data.json (restaurant refund payload with
|
||||||
// shown in money_return_receipt.jpg (original invoice reference, refund type, tip).
|
// Unix-ms timestamps and per-rate VAT breakdown).
|
||||||
public static MoneyReturnReceipt BuildSampleMoneyReturnReceipt()
|
public static MoneyReturnReceipt BuildSampleMoneyReturnReceipt()
|
||||||
{
|
{
|
||||||
var receipt = new MoneyReturnReceipt
|
return new MoneyReturnReceipt
|
||||||
{
|
{
|
||||||
CompanyName = "Big Mac Bistro",
|
RestaurantName = "Gaumenfreuden",
|
||||||
Address1 = "Zelena 186",
|
RestaurantPhoneNumber = "043 810 48 48",
|
||||||
Address2 = "79000 Lviv",
|
RestaurantAddressLine1 = "Seestrasse 11",
|
||||||
Phone = "080 039 47 69",
|
RestaurantAddressLine2 = "8810 Horgen",
|
||||||
ReceiptNumber = "25",
|
RestaurantWebsite = "https://gaumen-freuden.ch",
|
||||||
DateTime = new DateTime(2026, 7, 4, 11, 8, 13),
|
RestaurantVatNumber = null,
|
||||||
Guests = 1,
|
ThanksMessage = "Thank you for your order!",
|
||||||
Total = 20.00m,
|
NoVAT = false,
|
||||||
|
RefundReceiptId = null,
|
||||||
|
RefundNumber = 1,
|
||||||
|
RefundTimestamp = 1783522075649,
|
||||||
|
OriginalTransactionNumber = 186,
|
||||||
|
OriginalPaymentTimestamp = 1783521986035,
|
||||||
|
OriginalPaymentMethod = "Cash",
|
||||||
Currency = "CHF",
|
Currency = "CHF",
|
||||||
PaymentMethod = "Cash",
|
RefundType = "Full",
|
||||||
PaymentAmount = 13.00m,
|
TipAmount = 0.3m,
|
||||||
WaiterName = "Ronald McDonald",
|
RefundedAmount = 11.0m,
|
||||||
VatNumber = " MWST",
|
RefundPaymentMethod = "Cash",
|
||||||
ThankYouMessage = "Thank you for your order!",
|
RefundedItems = new List<RefundedItem>
|
||||||
GoodbyeMessageLine1 = "Auf Wiedersehen.",
|
{
|
||||||
GoodbyeMessageLine2 = "Powered by James",
|
new() { Name = "Cappuccino", Size = "", Quantity = 1, Price = 5.8m, TaxAbbr = "A" },
|
||||||
// Credit-note specific fields
|
new() { Name = "Kaffee Crème", Size = "", Quantity = 1, Price = 4.9m, TaxAbbr = "A" }
|
||||||
OriginalInvoiceNumber = "773",
|
},
|
||||||
OriginalDateTime = new DateTime(2026, 7, 4, 11, 7, 0),
|
StandardRate = new TaxRateBreakdown
|
||||||
RefundType = "Full refund",
|
{
|
||||||
Tip = 7.00m
|
Rate = 8.1m,
|
||||||
|
TotalAmount = 10.7m,
|
||||||
|
TotalAmountNetto = 9.90m,
|
||||||
|
TotalAmountTax = 0.80m
|
||||||
|
},
|
||||||
|
ReducedRate = new TaxRateBreakdown { Rate = 0m, TotalAmount = 0m, TotalAmountNetto = 0m, TotalAmountTax = 0m },
|
||||||
|
SpecialRateForAccommodation = new TaxRateBreakdown { Rate = 0m, TotalAmount = 0m, TotalAmountNetto = 0m, TotalAmountTax = 0m }
|
||||||
};
|
};
|
||||||
|
|
||||||
receipt.Items.Add(new MoneyReturnReceiptItem
|
|
||||||
{
|
|
||||||
Quantity = 1,
|
|
||||||
Description = "Cloudy Bay Sauvignon Blanc 2024",
|
|
||||||
UnitPrice = 13.00m,
|
|
||||||
TotalPrice = 13.00m,
|
|
||||||
TaxCategory = "D"
|
|
||||||
});
|
|
||||||
|
|
||||||
receipt.Items.Add(new MoneyReturnReceiptItem
|
|
||||||
{
|
|
||||||
Quantity = 1,
|
|
||||||
Description = "Trinkgeld",
|
|
||||||
UnitPrice = 7.00m,
|
|
||||||
TotalPrice = 7.00m,
|
|
||||||
TaxCategory = "D"
|
|
||||||
});
|
|
||||||
|
|
||||||
receipt.TaxBreakdown.Add(new MoneyReturnTaxInfo
|
|
||||||
{
|
|
||||||
Category = "D",
|
|
||||||
Rate = 0m,
|
|
||||||
Gross = 20.00m,
|
|
||||||
Net = 20.00m,
|
|
||||||
TaxAmount = 0.00m,
|
|
||||||
Currency = "CHF"
|
|
||||||
});
|
|
||||||
|
|
||||||
return receipt;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@@ -559,7 +541,7 @@ public static class TestHelpers
|
|||||||
public static async Task PrintCommandsToEpsonPrinterAsync(
|
public static async Task PrintCommandsToEpsonPrinterAsync(
|
||||||
EpsonPrinter printer,
|
EpsonPrinter printer,
|
||||||
IEnumerable<PrintCommand> commands,
|
IEnumerable<PrintCommand> commands,
|
||||||
bool useDelay = true,
|
bool useDelay = false,
|
||||||
int delayMs = 200)
|
int delayMs = 200)
|
||||||
{
|
{
|
||||||
await printer.FeedLinesAsync(1);
|
await printer.FeedLinesAsync(1);
|
||||||
|
|||||||
@@ -1,118 +1,97 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace Inspectron.Epson.PrintServer.Printers.Utils.MoneyReturnReceipt;
|
namespace Inspectron.Epson.PrintServer.Printers.Utils.MoneyReturnReceipt;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Data model for a refund / credit note ("money return") receipt.
|
/// Data model for a refund / credit note ("money return") receipt.
|
||||||
/// Mirrors the sale receipt payload (see money_return_receipt_data.json) and adds
|
/// Matches the refund payload (see money_return_receipt_data.json / data (1).json):
|
||||||
/// the credit-note specific fields that reference the original invoice being refunded.
|
/// restaurant header info, original transaction reference, refunded items and the
|
||||||
|
/// per-rate VAT breakdown. Timestamps are Unix epoch milliseconds.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class MoneyReturnReceipt
|
public class MoneyReturnReceipt
|
||||||
{
|
{
|
||||||
public string CompanyName { get; set; }
|
/// <summary>Base64-encoded restaurant logo (optional). Rendered by the print pipeline, not the text converter.</summary>
|
||||||
public string Address1 { get; set; }
|
public string? RestaurantLogo { get; set; }
|
||||||
public string Address2 { get; set; }
|
|
||||||
public string Phone { get; set; }
|
|
||||||
|
|
||||||
/// <summary>Credit note number (shown as "Credit note No. {ReceiptNumber}").</summary>
|
public string RestaurantName { get; set; }
|
||||||
public string? ReceiptNumber { get; set; }
|
public string RestaurantPhoneNumber { get; set; }
|
||||||
|
public string RestaurantAddressLine1 { get; set; }
|
||||||
|
public string RestaurantAddressLine2 { get; set; }
|
||||||
|
public string RestaurantWebsite { get; set; }
|
||||||
|
|
||||||
/// <summary>Date/time the credit note was issued.</summary>
|
/// <summary>VAT registration number. Note the misspelled JSON key ("Restauant...").</summary>
|
||||||
public DateTime DateTime { get; set; }
|
[JsonPropertyName("RestauantVATNumber")]
|
||||||
|
public string? RestaurantVatNumber { get; set; }
|
||||||
|
|
||||||
public int Guests { get; set; }
|
public string ThanksMessage { get; set; }
|
||||||
public List<MoneyReturnReceiptItem> Items { get; set; } = new List<MoneyReturnReceiptItem>();
|
|
||||||
|
|
||||||
/// <summary>Refunded amount (positive). Rendered negative on the receipt.</summary>
|
/// <summary>When true the sale is not subject to VAT and the tax table is replaced by a note.</summary>
|
||||||
public decimal Total { get; set; }
|
public bool NoVAT { get; set; }
|
||||||
public string Currency { get; set; }
|
|
||||||
|
|
||||||
public decimal? TotalInAlternateCurrency { get; set; }
|
public long? RefundReceiptId { get; set; }
|
||||||
public string AlternateCurrency { get; set; }
|
|
||||||
|
|
||||||
public List<MoneyReturnSplitPaymentInfo> SplitPayments { get; set; } = new List<MoneyReturnSplitPaymentInfo>();
|
/// <summary>Credit note number (shown as "Credit note No. {RefundNumber}").</summary>
|
||||||
|
public long RefundNumber { get; set; }
|
||||||
|
|
||||||
|
/// <summary>When the refund was issued, as Unix epoch milliseconds.</summary>
|
||||||
|
public long RefundTimestamp { get; set; }
|
||||||
|
|
||||||
|
/// <summary>Number of the original transaction/invoice being refunded ("Orig. invoice No.").</summary>
|
||||||
|
public long OriginalTransactionNumber { get; set; }
|
||||||
|
|
||||||
|
/// <summary>When the original payment was made, as Unix epoch milliseconds ("Orig. date").</summary>
|
||||||
|
public long OriginalPaymentTimestamp { get; set; }
|
||||||
|
|
||||||
/// <summary>Method the original payment was made with (e.g. "Cash").</summary>
|
/// <summary>Method the original payment was made with (e.g. "Cash").</summary>
|
||||||
public string PaymentMethod { get; set; }
|
public string OriginalPaymentMethod { get; set; }
|
||||||
public decimal PaymentAmount { get; set; }
|
|
||||||
|
|
||||||
public List<MoneyReturnTaxInfo> TaxBreakdown { get; set; } = new List<MoneyReturnTaxInfo>();
|
public string Currency { get; set; }
|
||||||
|
|
||||||
public bool IsDebtor { get; set; } = false;
|
/// <summary>Refund type, e.g. "Full" or "Partial" (rendered as "Full refund").</summary>
|
||||||
public string WaiterName { get; set; }
|
public string RefundType { get; set; }
|
||||||
public string Terminal { get; set; }
|
|
||||||
public string TableNumber { get; set; }
|
|
||||||
public string VatNumber { get; set; }
|
|
||||||
|
|
||||||
public string ThankYouMessage { get; set; }
|
|
||||||
public string GoodbyeMessageLine1 { get; set; }
|
|
||||||
public string GoodbyeMessageLine2 { get; set; }
|
|
||||||
|
|
||||||
public List<MoneyReturnPaymentTerminalReceipt> TerminalReceipts { get; set; } = new List<MoneyReturnPaymentTerminalReceipt>();
|
|
||||||
public MoneyReturnDiscountInfo? DiscountInfo { get; set; }
|
|
||||||
|
|
||||||
// --- Credit-note specific fields ---
|
|
||||||
|
|
||||||
/// <summary>Number of the original invoice this credit note refunds ("Orig. invoice No.").</summary>
|
|
||||||
public string? OriginalInvoiceNumber { get; set; }
|
|
||||||
|
|
||||||
/// <summary>Date/time of the original invoice ("Orig. date").</summary>
|
|
||||||
public DateTime? OriginalDateTime { get; set; }
|
|
||||||
|
|
||||||
/// <summary>Refund type, e.g. "Full refund" or "Partial refund" ("Type").</summary>
|
|
||||||
public string? RefundType { get; set; }
|
|
||||||
|
|
||||||
/// <summary>Tip amount included in the refund. Shown as "incl. tip" when non-zero.</summary>
|
/// <summary>Tip amount included in the refund. Shown as "incl. tip" when non-zero.</summary>
|
||||||
public decimal Tip { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class MoneyReturnReceiptItem
|
|
||||||
{
|
|
||||||
public int Quantity { get; set; }
|
|
||||||
public string Description { get; set; }
|
|
||||||
public decimal UnitPrice { get; set; }
|
|
||||||
public decimal TotalPrice { get; set; }
|
|
||||||
public string TaxCategory { get; set; }
|
|
||||||
public List<string> SubItems { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class MoneyReturnTaxInfo
|
|
||||||
{
|
|
||||||
public string Category { get; set; }
|
|
||||||
public decimal Rate { get; set; }
|
|
||||||
public decimal Gross { get; set; }
|
|
||||||
public decimal Net { get; set; }
|
|
||||||
public decimal TaxAmount { get; set; }
|
|
||||||
public string Currency { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class MoneyReturnSplitPaymentInfo
|
|
||||||
{
|
|
||||||
public string PaymentMethod { get; set; }
|
|
||||||
public decimal Amount { get; set; }
|
|
||||||
public string Currency { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class MoneyReturnDiscountInfo
|
|
||||||
{
|
|
||||||
public string Description { get; set; }
|
|
||||||
public decimal Amount { get; set; }
|
|
||||||
public string Currency { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class MoneyReturnPaymentTerminalReceipt
|
|
||||||
{
|
|
||||||
public string ReceiptType { get; set; }
|
|
||||||
public string BookingType { get; set; }
|
|
||||||
public string PaymentSystem { get; set; }
|
|
||||||
public string TransactionNumber { get; set; }
|
|
||||||
public DateTime TransactionDateTime { get; set; }
|
|
||||||
public string TerminalId { get; set; }
|
|
||||||
public string AID { get; set; }
|
|
||||||
public string TransactionSeqCount { get; set; }
|
|
||||||
public string TransactionRefNo { get; set; }
|
|
||||||
public string AuthCode { get; set; }
|
|
||||||
public string AcquirerId { get; set; }
|
|
||||||
public decimal EftAmount { get; set; }
|
|
||||||
public decimal TipAmount { get; set; }
|
public decimal TipAmount { get; set; }
|
||||||
public decimal TotalEftAmount { get; set; }
|
|
||||||
public string Currency { get; set; }
|
public List<RefundedItem> RefundedItems { get; set; } = new List<RefundedItem>();
|
||||||
|
|
||||||
|
/// <summary>Total refunded amount (positive). Rendered negative on the receipt.</summary>
|
||||||
|
public decimal RefundedAmount { get; set; }
|
||||||
|
|
||||||
|
/// <summary>Standard-rate VAT bucket. Note the misspelled JSON key ("Standart...").</summary>
|
||||||
|
[JsonPropertyName("StandartRate")]
|
||||||
|
public TaxRateBreakdown StandardRate { get; set; }
|
||||||
|
|
||||||
|
public TaxRateBreakdown ReducedRate { get; set; }
|
||||||
|
|
||||||
|
public TaxRateBreakdown SpecialRateForAccommodation { get; set; }
|
||||||
|
|
||||||
|
/// <summary>Method the refund was paid out with (e.g. "Cash").</summary>
|
||||||
|
public string RefundPaymentMethod { get; set; }
|
||||||
|
|
||||||
|
public string TerminalReceiptData { get; set; }
|
||||||
|
public string WebPaymentReceiptData { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class RefundedItem
|
||||||
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
public string Size { get; set; }
|
||||||
|
public int Quantity { get; set; }
|
||||||
|
public decimal Price { get; set; }
|
||||||
|
public string TaxAbbr { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class TaxRateBreakdown
|
||||||
|
{
|
||||||
|
public decimal Rate { get; set; }
|
||||||
|
|
||||||
|
/// <summary>Gross amount at this rate.</summary>
|
||||||
|
public decimal TotalAmount { get; set; }
|
||||||
|
|
||||||
|
/// <summary>Net amount at this rate.</summary>
|
||||||
|
public decimal TotalAmountNetto { get; set; }
|
||||||
|
|
||||||
|
/// <summary>Tax amount at this rate.</summary>
|
||||||
|
public decimal TotalAmountTax { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ namespace Inspectron.Epson.PrintServer.Printers.Utils.MoneyReturnReceipt;
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Builds the print command list for a refund / credit note receipt.
|
/// Builds the print command list for a refund / credit note receipt.
|
||||||
/// Layout follows money_return_receipt.jpg: company header, "Refund / Credit note"
|
/// Layout follows money_return_receipt.jpg: restaurant header, "Refund / Credit note"
|
||||||
/// title, credit note + original invoice reference block, the negative credit total,
|
/// title, credit note + original transaction reference block, the negative credit total,
|
||||||
/// the (negated) VAT breakdown and the goodbye footer.
|
/// the (negated) per-rate VAT breakdown and the thank-you footer.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class ReceiptConverter
|
public class ReceiptConverter
|
||||||
{
|
{
|
||||||
@@ -21,11 +21,13 @@ public class ReceiptConverter
|
|||||||
{
|
{
|
||||||
var commands = new List<PrintCommand>();
|
var commands = new List<PrintCommand>();
|
||||||
|
|
||||||
// Header - Company info
|
// Header - Restaurant info
|
||||||
commands.Add(new PrintCommand(Center(receipt.CompanyName, false)));
|
commands.Add(new PrintCommand(Center(receipt.RestaurantName, false)));
|
||||||
commands.Add(new PrintCommand(Center(receipt.Address1, false)));
|
commands.Add(new PrintCommand(Center(receipt.RestaurantAddressLine1, false)));
|
||||||
commands.Add(new PrintCommand(Center(receipt.Address2, false)));
|
commands.Add(new PrintCommand(Center(receipt.RestaurantAddressLine2, false)));
|
||||||
commands.Add(new PrintCommand(Center(receipt.Phone, false)));
|
commands.Add(new PrintCommand(Center(receipt.RestaurantPhoneNumber, false)));
|
||||||
|
if (!string.IsNullOrWhiteSpace(receipt.RestaurantWebsite))
|
||||||
|
commands.Add(new PrintCommand(Center(receipt.RestaurantWebsite, false)));
|
||||||
commands.Add(new PrintCommand(""));
|
commands.Add(new PrintCommand(""));
|
||||||
commands.Add(new PrintCommand(""));
|
commands.Add(new PrintCommand(""));
|
||||||
|
|
||||||
@@ -36,93 +38,96 @@ public class ReceiptConverter
|
|||||||
commands.Add(new PrintCommand(""));
|
commands.Add(new PrintCommand(""));
|
||||||
|
|
||||||
// Credit note number + issue date
|
// Credit note number + issue date
|
||||||
string creditNoteLabel = receipt.ReceiptNumber != null
|
commands.Add(new PrintCommand(Justify(
|
||||||
? $"Credit note No. {receipt.ReceiptNumber}"
|
$"Credit note No. {receipt.RefundNumber}",
|
||||||
: "Credit note";
|
FormatTimestamp(receipt.RefundTimestamp))));
|
||||||
commands.Add(new PrintCommand(Justify(creditNoteLabel, $"{receipt.DateTime:HH:mm dd.MM.yyyy}")));
|
|
||||||
commands.Add(new PrintCommand(""));
|
commands.Add(new PrintCommand(""));
|
||||||
|
|
||||||
// Original invoice reference block
|
// Original transaction reference block
|
||||||
commands.Add(new PrintCommand(Justify("Orig. invoice No.:", receipt.OriginalInvoiceNumber ?? "")));
|
commands.Add(new PrintCommand(Justify("Orig. invoice No.:", receipt.OriginalTransactionNumber.ToString())));
|
||||||
if (receipt.OriginalDateTime.HasValue)
|
commands.Add(new PrintCommand(Justify("Orig. date:", FormatTimestamp(receipt.OriginalPaymentTimestamp))));
|
||||||
commands.Add(new PrintCommand(Justify("Orig. date:", $"{receipt.OriginalDateTime:HH:mm dd.MM.yyyy}")));
|
commands.Add(new PrintCommand(Justify("Orig. payment method:", receipt.OriginalPaymentMethod ?? "")));
|
||||||
commands.Add(new PrintCommand(Justify("Orig. payment method:", receipt.PaymentMethod ?? "")));
|
|
||||||
if (!string.IsNullOrEmpty(receipt.RefundType))
|
if (!string.IsNullOrEmpty(receipt.RefundType))
|
||||||
commands.Add(new PrintCommand(Justify("Type:", receipt.RefundType)));
|
commands.Add(new PrintCommand(Justify("Type:", $"{receipt.RefundType} refund")));
|
||||||
commands.Add(new PrintCommand(""));
|
commands.Add(new PrintCommand(""));
|
||||||
|
|
||||||
commands.Add(new PrintCommand(new string('-', _lineWidth)));
|
commands.Add(new PrintCommand(new string('-', _lineWidth)));
|
||||||
commands.Add(new PrintCommand(""));
|
commands.Add(new PrintCommand(""));
|
||||||
|
|
||||||
// Included tip
|
// Included tip
|
||||||
if (receipt.Tip != 0)
|
if (receipt.TipAmount != 0)
|
||||||
{
|
{
|
||||||
commands.Add(new PrintCommand($"incl. tip {receipt.Currency}: {receipt.Tip:F2}".PadLeft(_lineWidth)));
|
commands.Add(new PrintCommand($"incl. tip {receipt.Currency}: {receipt.TipAmount:F2}".PadLeft(_lineWidth)));
|
||||||
commands.Add(new PrintCommand(""));
|
commands.Add(new PrintCommand(""));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Credit total (refund is shown as a negative amount), big + bold, centered
|
// Credit total (refund is shown as a negative amount), big + bold, centered
|
||||||
string creditLine = $"Credit: {-receipt.Total:F2} {receipt.Currency}";
|
string creditLine = $"Credit: {-receipt.RefundedAmount:F2} {receipt.Currency}";
|
||||||
commands.Add(new PrintCommand(Center(creditLine, true), true, true));
|
commands.Add(new PrintCommand(Center(creditLine, true), true, true));
|
||||||
commands.Add(new PrintCommand(""));
|
commands.Add(new PrintCommand(""));
|
||||||
|
|
||||||
// Alternate currency
|
// Refund payment method line (e.g. "Cash: -11.00 CHF")
|
||||||
if (receipt.TotalInAlternateCurrency.HasValue)
|
commands.Add(new PrintCommand($"{receipt.RefundPaymentMethod}: {-receipt.RefundedAmount:F2} {receipt.Currency}".PadLeft(_lineWidth)));
|
||||||
{
|
|
||||||
string altCurrencyLine = $"{-receipt.TotalInAlternateCurrency:F2} {receipt.AlternateCurrency}";
|
|
||||||
commands.Add(new PrintCommand(altCurrencyLine.PadLeft(_lineWidth)));
|
|
||||||
commands.Add(new PrintCommand(""));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Refund payment method line (e.g. "Cash: -20.00 CHF")
|
|
||||||
if (receipt.SplitPayments != null && receipt.SplitPayments.Count > 0)
|
|
||||||
{
|
|
||||||
foreach (var split in receipt.SplitPayments)
|
|
||||||
commands.Add(new PrintCommand($"{split.PaymentMethod}: {-split.Amount:F2} {split.Currency}".PadLeft(_lineWidth)));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
commands.Add(new PrintCommand($"{receipt.PaymentMethod}: {-receipt.Total:F2} {receipt.Currency}".PadLeft(_lineWidth)));
|
|
||||||
}
|
|
||||||
commands.Add(new PrintCommand(""));
|
commands.Add(new PrintCommand(""));
|
||||||
|
|
||||||
// Tax breakdown (amounts negated for the refund)
|
// VAT breakdown (amounts negated for the refund)
|
||||||
foreach (var tax in receipt.TaxBreakdown)
|
if (receipt.NoVAT)
|
||||||
{
|
|
||||||
if (receipt.TaxBreakdown.IndexOf(tax) == 0)
|
|
||||||
{
|
|
||||||
string taxHeader = "VAT %".PadRight(_lineWidth / 4)
|
|
||||||
+ "Gross".PadLeft(_lineWidth / 4)
|
|
||||||
+ "Net".PadLeft(_lineWidth / 4)
|
|
||||||
+ "VAT".PadLeft(_lineWidth / 4);
|
|
||||||
commands.Add(new PrintCommand(taxHeader));
|
|
||||||
}
|
|
||||||
|
|
||||||
string taxDetail = ($"{tax.Category}:" + $"{tax.Rate}%".PadLeft(5)).PadRight(_lineWidth / 4)
|
|
||||||
+ $"{-tax.Gross:F2} {tax.Currency}".PadLeft(_lineWidth / 4)
|
|
||||||
+ $"{-tax.Net:F2} {tax.Currency}".PadLeft(_lineWidth / 4)
|
|
||||||
+ $"{-tax.TaxAmount:F2} {tax.Currency}".PadLeft(_lineWidth / 4);
|
|
||||||
commands.Add(new PrintCommand(taxDetail));
|
|
||||||
}
|
|
||||||
|
|
||||||
commands.Add(new PrintCommand(""));
|
|
||||||
|
|
||||||
if (receipt.TaxBreakdown.Count(x => x.Category != null && x.Category.ToLower() != "d") == 0)
|
|
||||||
{
|
{
|
||||||
commands.Add(new PrintCommand("Not subject to value added tax"));
|
commands.Add(new PrintCommand("Not subject to value added tax"));
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var rates = new List<(string Category, TaxRateBreakdown Rate)>();
|
||||||
|
AddIfPresent(rates, "A", receipt.StandardRate);
|
||||||
|
AddIfPresent(rates, "B", receipt.ReducedRate);
|
||||||
|
AddIfPresent(rates, "C", receipt.SpecialRateForAccommodation);
|
||||||
|
|
||||||
|
if (rates.Count > 0)
|
||||||
|
{
|
||||||
|
commands.Add(new PrintCommand("VAT %".PadRight(_lineWidth / 4)
|
||||||
|
+ "Gross".PadLeft(_lineWidth / 4)
|
||||||
|
+ "Net".PadLeft(_lineWidth / 4)
|
||||||
|
+ "VAT".PadLeft(_lineWidth / 4)));
|
||||||
|
|
||||||
|
foreach (var (category, rate) in rates)
|
||||||
|
{
|
||||||
|
commands.Add(new PrintCommand(
|
||||||
|
($"{category}:" + $"{rate.Rate}%".PadLeft(5)).PadRight(_lineWidth / 4)
|
||||||
|
+ $"{-rate.TotalAmount:F2} {receipt.Currency}".PadLeft(_lineWidth / 4)
|
||||||
|
+ $"{-rate.TotalAmountNetto:F2} {receipt.Currency}".PadLeft(_lineWidth / 4)
|
||||||
|
+ $"{-rate.TotalAmountTax:F2} {receipt.Currency}".PadLeft(_lineWidth / 4)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
commands.Add(new PrintCommand(""));
|
||||||
|
|
||||||
|
// VAT registration number (if provided)
|
||||||
|
if (!string.IsNullOrWhiteSpace(receipt.RestaurantVatNumber))
|
||||||
|
{
|
||||||
|
commands.Add(new PrintCommand(Center(receipt.RestaurantVatNumber, false)));
|
||||||
|
}
|
||||||
|
|
||||||
commands.Add(new PrintCommand(""));
|
commands.Add(new PrintCommand(""));
|
||||||
commands.Add(new PrintCommand(""));
|
commands.Add(new PrintCommand(""));
|
||||||
|
|
||||||
// Footer / goodbye
|
// Footer
|
||||||
commands.Add(new PrintCommand(Center(receipt.ThankYouMessage, false)));
|
commands.Add(new PrintCommand(Center(receipt.ThanksMessage, false)));
|
||||||
commands.Add(new PrintCommand(Center(receipt.GoodbyeMessageLine1, false)));
|
|
||||||
commands.Add(new PrintCommand(Center(receipt.GoodbyeMessageLine2, false)));
|
|
||||||
|
|
||||||
return commands;
|
return commands;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void AddIfPresent(List<(string, TaxRateBreakdown)> rates, string category, TaxRateBreakdown? rate)
|
||||||
|
{
|
||||||
|
if (rate != null && (rate.Rate != 0 || rate.TotalAmount != 0))
|
||||||
|
rates.Add((category, rate));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string FormatTimestamp(long unixMilliseconds)
|
||||||
|
{
|
||||||
|
return DateTimeOffset.FromUnixTimeMilliseconds(unixMilliseconds).LocalDateTime.ToString("HH:mm dd.MM.yyyy");
|
||||||
|
}
|
||||||
|
|
||||||
private string Justify(string left, string right)
|
private string Justify(string left, string right)
|
||||||
{
|
{
|
||||||
left ??= "";
|
left ??= "";
|
||||||
|
|||||||
57
data (1).json
Normal file
57
data (1).json
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
{
|
||||||
|
"RestaurantName":"Gaumenfreuden",
|
||||||
|
"RestaurantPhoneNumber":"043 810 48 48",
|
||||||
|
"RestaurantAddressLine1":"Seestrasse 11",
|
||||||
|
"RestaurantAddressLine2":"8810 Horgen",
|
||||||
|
"RestaurantWebsite":"https://gaumen-freuden.ch",
|
||||||
|
"RestauantVATNumber":null,
|
||||||
|
"ThanksMessage":"Thank you for your order!",
|
||||||
|
"NoVAT":false,
|
||||||
|
"RefundReceiptId":null,
|
||||||
|
"RefundNumber":1,
|
||||||
|
"RefundTimestamp":1783522075649,
|
||||||
|
"OriginalTransactionNumber":186,
|
||||||
|
"OriginalPaymentTimestamp":1783521986035,
|
||||||
|
"OriginalPaymentMethod":"Cash",
|
||||||
|
"Currency":"CHF",
|
||||||
|
"RefundType":"Full",
|
||||||
|
"TipAmount":0.3,
|
||||||
|
"RefundedItems":[
|
||||||
|
{
|
||||||
|
"Name":"Cappuccino",
|
||||||
|
"Size":"",
|
||||||
|
"Quantity":1,
|
||||||
|
"Price":5.8,
|
||||||
|
"TaxAbbr":"A"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name":"Kaffee Cr\u00E8me",
|
||||||
|
"Size":"",
|
||||||
|
"Quantity":1,
|
||||||
|
"Price":4.9,
|
||||||
|
"TaxAbbr":"A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"RefundedAmount":11.0,
|
||||||
|
"StandartRate":{
|
||||||
|
"Rate":8.1,
|
||||||
|
"TotalAmount":10.7,
|
||||||
|
"TotalAmountNetto":9.90,
|
||||||
|
"TotalAmountTax":0.80
|
||||||
|
},
|
||||||
|
"ReducedRate":{
|
||||||
|
"Rate":0,
|
||||||
|
"TotalAmount":0,
|
||||||
|
"TotalAmountNetto":0,
|
||||||
|
"TotalAmountTax":0
|
||||||
|
},
|
||||||
|
"SpecialRateForAccommodation":{
|
||||||
|
"Rate":0,
|
||||||
|
"TotalAmount":0,
|
||||||
|
"TotalAmountNetto":0,
|
||||||
|
"TotalAmountTax":0
|
||||||
|
},
|
||||||
|
"RefundPaymentMethod":"Cash",
|
||||||
|
"TerminalReceiptData":null,
|
||||||
|
"WebPaymentReceiptData":null
|
||||||
|
}
|
||||||
@@ -1,54 +1,58 @@
|
|||||||
{
|
{
|
||||||
"TotalInAlternateCurrency":null,
|
"RestaurantLogo":null,
|
||||||
"AlternateCurrency":"",
|
"RestaurantName":"Gaumenfreuden",
|
||||||
"SplitPayments":null,
|
"RestaurantPhoneNumber":"043 810 48 48",
|
||||||
"PaymentMethod":"Cash",
|
"RestaurantAddressLine1":"Seestrasse 11",
|
||||||
"PaymentAmount":13,
|
"RestaurantAddressLine2":"8810 Horgen",
|
||||||
"TaxBreakdown":[
|
"RestaurantWebsite":"https://gaumen-freuden.ch",
|
||||||
{
|
"RestauantVATNumber":null,
|
||||||
"Category":"D",
|
"ThanksMessage":"Thank you for your order!",
|
||||||
"Rate":0,
|
"NoVAT":false,
|
||||||
"Gross":20,
|
"RefundReceiptId":null,
|
||||||
"Net":20,
|
"RefundNumber":1,
|
||||||
"TaxAmount":0,
|
"RefundTimestamp":1783522075649,
|
||||||
"Currency":"CHF"
|
"OriginalTransactionNumber":186,
|
||||||
}
|
"OriginalPaymentTimestamp":1783521986035,
|
||||||
],
|
"OriginalPaymentMethod":"Cash",
|
||||||
"WaiterName":"Ronald McDonald",
|
"Currency":"CHF",
|
||||||
"Terminal":null,
|
"RefundType":"Full",
|
||||||
"VatNumber":" MWST",
|
"TipAmount":0.3,
|
||||||
"GoodbyeMessageLine1":"Auf Wiedersehen.",
|
"RefundedItems":[
|
||||||
"GoodbyeMessageLine2":"Powered by James",
|
|
||||||
"TerminalReceipts":null,
|
|
||||||
"IsDebtor":false,
|
|
||||||
"DiscountInfo":null,
|
|
||||||
"CompanyName":"Big Mac Bistro",
|
|
||||||
"Address1":"Zelena 186",
|
|
||||||
"Address2":"79000 Lviv",
|
|
||||||
"Phone":"080 039 47 69",
|
|
||||||
"ReceiptNumber":"25",
|
|
||||||
"DateTime":"2026-07-04T11:08:13.861",
|
|
||||||
"Guests":1,
|
|
||||||
"Items":[
|
|
||||||
{
|
{
|
||||||
|
"Name":"Cappuccino",
|
||||||
|
"Size":"",
|
||||||
"Quantity":1,
|
"Quantity":1,
|
||||||
"Description":"Cloudy Bay Sauvignon Blanc 2024",
|
"Price":5.8,
|
||||||
"UnitPrice":13,
|
"TaxAbbr":"A"
|
||||||
"TotalPrice":13,
|
|
||||||
"TaxCategory":"D",
|
|
||||||
"SubItems":null
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"Name":"Kaffee Crème",
|
||||||
|
"Size":"",
|
||||||
"Quantity":1,
|
"Quantity":1,
|
||||||
"Description":"Trinkgeld",
|
"Price":4.9,
|
||||||
"UnitPrice":7,
|
"TaxAbbr":"A"
|
||||||
"TotalPrice":7,
|
|
||||||
"TaxCategory":"D",
|
|
||||||
"SubItems":null
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"Total":20,
|
"RefundedAmount":11.0,
|
||||||
"Currency":"CHF",
|
"StandartRate":{
|
||||||
"ThankYouMessage":"Thank you for your order!",
|
"Rate":8.1,
|
||||||
"TableNumber":null
|
"TotalAmount":10.7,
|
||||||
}
|
"TotalAmountNetto":9.90,
|
||||||
|
"TotalAmountTax":0.80
|
||||||
|
},
|
||||||
|
"ReducedRate":{
|
||||||
|
"Rate":0,
|
||||||
|
"TotalAmount":0,
|
||||||
|
"TotalAmountNetto":0,
|
||||||
|
"TotalAmountTax":0
|
||||||
|
},
|
||||||
|
"SpecialRateForAccommodation":{
|
||||||
|
"Rate":0,
|
||||||
|
"TotalAmount":0,
|
||||||
|
"TotalAmountNetto":0,
|
||||||
|
"TotalAmountTax":0
|
||||||
|
},
|
||||||
|
"RefundPaymentMethod":"Cash",
|
||||||
|
"TerminalReceiptData":null,
|
||||||
|
"WebPaymentReceiptData":null
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user