klinglers special

This commit is contained in:
EugeneTes
2026-02-25 10:35:20 +01:00
parent 11dfd6ead4
commit be83fadc5f
5 changed files with 166 additions and 75 deletions

View File

@@ -44,9 +44,9 @@ using System.Text.Json;
// INVOICE RECEIPT - HTML PRINTER
// ============================================================================
//var receipt = TestHelpers.BuildSampleInvoiceReceipt();
////var serializedReceipt = JsonSerializer.Serialize(receipt, new JsonSerializerOptions { WriteIndented = true });
//var fileContent = File.ReadAllText("invoice.json");
//var serializedReceipt = JsonSerializer.Deserialize<string>(fileContent);
//var serializedReceipt = JsonSerializer.Serialize(receipt, new JsonSerializerOptions { WriteIndented = true });
////var fileContent = File.ReadAllText("invoice.json");
////var serializedReceipt = JsonSerializer.Deserialize<string>(fileContent);
//var converter = new InvoiceReceiptConverter(lineWidth: 48, bigFontLineWidth: 24);
//var printCommands = converter.Convert(serializedReceipt);

View File

@@ -251,7 +251,7 @@ public static class TestHelpers
receipt.Items.Add(new Inspectron.Epson.PrintServer.Printers.Utils.InvoiceReceipt.ReceiptItem
{
Quantity = 1,
Description = "Granini Tomatensaft",
Description = "Granini Tomatensaft with something long to cause line wrapping more and more",
UnitPrice = 5.50m,
TotalPrice = 5.50m,
TaxCategory = "A"
@@ -312,7 +312,7 @@ public static class TestHelpers
receipt.Gangs.Add(new Gang(1, "Gang"));
receipt.Gangs.Add(new Gang(2, "Gang"));
receipt.Gangs[0].Dishes.Add(new Dish(1, "Avocado Sashimi")
receipt.Gangs[0].Dishes.Add(new Dish(1, "Avocado Sashimi with some addition to cause line wrapping")
{
Size = "XL",
Modifications = new DishModifications
@@ -321,10 +321,11 @@ public static class TestHelpers
Added = new List<string> { "Extra Ginger" }
},
Comment = "No soy sauce",
GuestId = 1
GuestId = 1,
Price = 123.45m
});
receipt.Gangs[0].Dishes.Add(new Dish(2, "Avocado Sashimi") { GuestId = 2 });
receipt.Gangs[0].Dishes.Add(new Dish(1, "Avocado Sashimi") { GuestId = 3 });
receipt.Gangs[0].Dishes.Add(new Dish(2, "Avocado Sashimi with some addition to cause line wrapping") { GuestId = 2 });
receipt.Gangs[0].Dishes.Add(new Dish(1, "Avocado Sashimi with some addition to cause line wrapping") { GuestId = 3 });
receipt.Gangs[0].Dishes.Add(new Dish(1, "Baby Spinach Salad with Truffl"){GuestId = 2});
//receipt.Gangs[0].Dishes.Add(new Dish(1, "Beef Tataki")
//{

View File

@@ -43,24 +43,7 @@ public class ReceiptConverter
// Items
foreach (var item in invoiceReceipt.Items)
{
string quantityDesc = $"{item.Quantity}x {item.Description}";
string prices = $"{item.UnitPrice:F2}"+$"{item.TotalPrice:F2}".PadLeft(7)+$" {item.TaxCategory}";
// Calculate spacing to align prices to the right
int spacesNeeded = _lineWidth - quantityDesc.Length - prices.Length;
if (spacesNeeded < 1) spacesNeeded = 1;
string itemLine = quantityDesc + new string(' ', spacesNeeded) + prices;
commands.Add(new PrintCommand(itemLine));
// SubItems
if (item.SubItems != null)
{
foreach (var subItem in item.SubItems)
{
commands.Add(new PrintCommand($" - {subItem}"));
}
}
PrintItem(item, commands);
}
commands.Add(new PrintCommand(""));
@@ -70,12 +53,96 @@ public class ReceiptConverter
// Total
string totalLine = $"Summe: {invoiceReceipt.Total:F2} {invoiceReceipt.Currency}";
commands.Add(new PrintCommand(Center(totalLine, true), true, true));
commands.Add(new PrintCommand(""));
commands.Add(new PrintCommand(Center($"Tisch: {invoiceReceipt.TableNumber}",false), false));
commands.Add(new PrintCommand(Center(invoiceReceipt.ThankYouMessage, false)));
commands.Add(new PrintCommand(""));
commands.Add(new PrintCommand(Center("Zwischenrechnung", false),isBold:true));
return commands;
}
private void PrintItem(ReceiptItem item, List<PrintCommand> commands)
{
string quantityPrefix = $"{item.Quantity}x ";
string prices = $"{item.UnitPrice:F2}" + $"{item.TotalPrice:F2}".PadLeft(7) + $" {item.TaxCategory}";
string fullLine = quantityPrefix + item.Description;
int spacesNeeded = _lineWidth - fullLine.Length - prices.Length;
if (spacesNeeded >= 1 || string.IsNullOrEmpty(item.Description))
{
if (spacesNeeded < 1) spacesNeeded = 1;
commands.Add(new PrintCommand(fullLine + new string(' ', spacesNeeded) + prices));
}
else
{
int descriptionAvailable = _lineWidth - quantityPrefix.Length - prices.Length - 1;
if (descriptionAvailable <= 0)
{
commands.Add(new PrintCommand(fullLine));
}
else
{
var words = item.Description.Split(' ');
var lines = new List<string>();
string currentLine = "";
foreach (var word in words)
{
if (currentLine.Length == 0)
{
currentLine = word;
}
else if (currentLine.Length + 1 + word.Length <= descriptionAvailable)
{
currentLine += " " + word;
}
else
{
lines.Add(currentLine);
currentLine = word;
}
}
if (currentLine.Length > 0)
{
lines.Add(currentLine);
}
// First line with prefix and right-aligned prices
string firstLineText = quantityPrefix + lines[0];
int firstSpaces = _lineWidth - firstLineText.Length - prices.Length;
if (firstSpaces >= 1)
{
commands.Add(new PrintCommand(firstLineText + new string(' ', firstSpaces) + prices));
}
else
{
commands.Add(new PrintCommand(firstLineText));
commands.Add(new PrintCommand(prices.PadLeft(_lineWidth)));
}
// Continuation lines indented to align with description
string continuationIndent = new string(' ', quantityPrefix.Length);
for (int i = 1; i < lines.Count; i++)
{
commands.Add(new PrintCommand(continuationIndent + lines[i]));
}
}
}
// SubItems
if (item.SubItems != null)
{
foreach (var subItem in item.SubItems)
{
commands.Add(new PrintCommand($" - {subItem}"));
}
}
}
private string Center(string text, bool isBigFont)
{
int effectiveLineWidth = isBigFont ? _bigFontLineWidth : _lineWidth;

View File

@@ -99,6 +99,7 @@ public class KitchenReceiptConverterKlinglers
if (!string.IsNullOrEmpty(dish.Size)) return false;
if (!string.IsNullOrEmpty(dish.Comment)) return false;
if (dish.Modifications != null && (dish.Modifications.Removed.Any() || dish.Modifications.Added.Any())) return false;
if (dish.Price != null) return false;
return true;
}
@@ -117,11 +118,11 @@ public class KitchenReceiptConverterKlinglers
int totalQuantity = group.Sum(d => d.Number);
var guestIds = group
.Where(d => d.GuestId.HasValue)
.Select(d => d.GuestId.Value)
.SelectMany(d => Enumerable.Repeat(d.GuestId!.Value, d.Number))
.OrderBy(id => id)
.ToList();
PrintDishLine($"{totalQuantity}x ", group.Key, null, commands);
PrintDishLine($"{totalQuantity}x ", group.Key, null, null, commands);
if (guestIds.Any())
{
@@ -133,7 +134,7 @@ public class KitchenReceiptConverterKlinglers
// Print individual dishes (have size, modifications, or comment)
foreach (var dish in individual)
{
PrintDishLine($"{dish.Number}x ", dish.Name, dish.Size, commands);
PrintDishLine($"{dish.Number}x ", dish.Name, dish.Size, dish.Price, commands);
if (dish.GuestId.HasValue)
{
@@ -160,67 +161,88 @@ public class KitchenReceiptConverterKlinglers
}
}
private void PrintDishLine(string quantityPrefix, string dishName, string? size, List<PrintCommand> commands)
private void PrintDishLine(string quantityPrefix, string dishName, string? size, decimal? price, List<PrintCommand> commands)
{
string fullLine = quantityPrefix + dishName;
string? priceStr = price != null ? price.Value.ToString("0.00") : null;
string nameWithSize = dishName;
if (!string.IsNullOrEmpty(size))
{
fullLine += $" ({size})";
nameWithSize += $" ({size})";
}
if (fullLine.Length <= _lineWidth || string.IsNullOrEmpty(dishName))
int firstLineNameWidth = _lineWidth - quantityPrefix.Length - 6;
if (priceStr != null)
{
commands.Add(new PrintCommand(fullLine) { IsTall = true });
firstLineNameWidth -= priceStr.Length + 1;
}
else
int continuationNameWidth = _lineWidth - quantityPrefix.Length - 6;
// Simple case: name fits on first line
if (nameWithSize.Length <= firstLineNameWidth || string.IsNullOrEmpty(dishName))
{
int availableWidth = _lineWidth - quantityPrefix.Length;
if (availableWidth <= 0)
string line = quantityPrefix + nameWithSize;
if (priceStr != null)
{
commands.Add(new PrintCommand(fullLine) { IsTall = true });
int padding = _lineWidth - line.Length - priceStr.Length;
line += new string(' ', Math.Max(1, padding)) + priceStr;
}
commands.Add(new PrintCommand(line) { IsTall = true });
return;
}
if (firstLineNameWidth <= 0)
{
string line = quantityPrefix + nameWithSize;
if (priceStr != null) line += " " + priceStr;
commands.Add(new PrintCommand(line) { IsTall = true });
return;
}
// Word wrap
var words = nameWithSize.Split(' ');
var lines = new List<string>();
string currentLine = "";
int currentMaxWidth = firstLineNameWidth;
foreach (var word in words)
{
if (currentLine.Length == 0)
{
currentLine = word;
}
else if (currentLine.Length + 1 + word.Length <= currentMaxWidth)
{
currentLine += " " + word;
}
else
{
string nameWithSize = dishName;
if (!string.IsNullOrEmpty(size))
{
nameWithSize += $" ({size})";
}
var words = nameWithSize.Split(' ');
var lines = new List<string>();
string currentLine = "";
foreach (var word in words)
{
if (currentLine.Length == 0)
{
currentLine = word;
}
else if (currentLine.Length + 1 + word.Length <= availableWidth)
{
currentLine += " " + word;
}
else
{
lines.Add(currentLine);
currentLine = word;
}
}
if (currentLine.Length > 0)
{
lines.Add(currentLine);
}
commands.Add(new PrintCommand(quantityPrefix + lines[0]) { IsTall = true });
string indent = new string(' ', quantityPrefix.Length);
for (int i = 1; i < lines.Count; i++)
{
commands.Add(new PrintCommand(indent + lines[i]) { IsTall = true });
}
lines.Add(currentLine);
currentLine = word;
currentMaxWidth = continuationNameWidth;
}
}
if (currentLine.Length > 0)
{
lines.Add(currentLine);
}
// First line with prefix and optional right-aligned price
string firstLine = quantityPrefix + lines[0];
if (priceStr != null)
{
int padding = _lineWidth - firstLine.Length - priceStr.Length;
firstLine += new string(' ', Math.Max(1, padding)) + priceStr;
}
commands.Add(new PrintCommand(firstLine) { IsTall = true });
// Continuation lines
string indent = new string(' ', quantityPrefix.Length);
for (int i = 1; i < lines.Count; i++)
{
commands.Add(new PrintCommand(indent + lines[i]) { IsTall = true });
}
}
private string Center(string text, bool isBigFont)

View File

@@ -84,6 +84,7 @@
public DishModifications Modifications { get; set; } = new DishModifications();
public string? Comment { get; set; }
public decimal? Price { get; set; }
}
public class DishModifications