From 11dfd6ead401825a7d6aea14580bf2aee3d4b4c5 Mon Sep 17 00:00:00 2001 From: EugeneTes Date: Tue, 24 Feb 2026 11:54:19 +0100 Subject: [PATCH] grouping in kitchen receipt --- EpsonTest/Program.cs | 2 +- EpsonTest/TestHelpers.cs | 2 + .../KitchenReceiptConverterAdapter.cs | 2 +- .../KitchenReceiptConverterKlinglers.cs | 247 ++++++++++++++++++ 4 files changed, 251 insertions(+), 2 deletions(-) create mode 100644 Inspectron.Epson/PrintServer/Printers/Utils/KitchenReceipt/KitchenReceiptConverterKlinglers.cs diff --git a/EpsonTest/Program.cs b/EpsonTest/Program.cs index 141b219..1b7d6ca 100644 --- a/EpsonTest/Program.cs +++ b/EpsonTest/Program.cs @@ -81,7 +81,7 @@ var receipt = TestHelpers.BuildSampleKitchenReceipt(); var serializedReceipt = JsonSerializer.Serialize(receipt, new JsonSerializerOptions { WriteIndented = true }); var deserializedReceipt = JsonSerializer.Deserialize(serializedReceipt); -var converter = new KitchenReceiptConverter(bigLineWidth: 20, lineWidth: 33); +var converter = new KitchenReceiptConverterKlinglers(bigLineWidth: 20, lineWidth: 33); var printCommands = converter.ConvertToPrintCommands(deserializedReceipt); TestHelpers.PrintCommandsToConsole(printCommands); diff --git a/EpsonTest/TestHelpers.cs b/EpsonTest/TestHelpers.cs index 3293bc6..2a2a25c 100644 --- a/EpsonTest/TestHelpers.cs +++ b/EpsonTest/TestHelpers.cs @@ -323,6 +323,8 @@ public static class TestHelpers Comment = "No soy sauce", GuestId = 1 }); + 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(1, "Baby Spinach Salad with Truffl"){GuestId = 2}); //receipt.Gangs[0].Dishes.Add(new Dish(1, "Beef Tataki") //{ diff --git a/Inspectron.Epson/PrintServer/Printers/Utils/KitchenReceipt/KitchenReceiptConverterAdapter.cs b/Inspectron.Epson/PrintServer/Printers/Utils/KitchenReceipt/KitchenReceiptConverterAdapter.cs index 2f8e94f..97abeb0 100644 --- a/Inspectron.Epson/PrintServer/Printers/Utils/KitchenReceipt/KitchenReceiptConverterAdapter.cs +++ b/Inspectron.Epson/PrintServer/Printers/Utils/KitchenReceipt/KitchenReceiptConverterAdapter.cs @@ -16,7 +16,7 @@ public class KitchenReceiptConverterAdapter : IReceiptConverter public List Convert(string jsonContent) { var receipt = JsonSerializer.Deserialize(jsonContent); - var converter = new KitchenReceiptConverter(_lineWidth, _bigFontLineWidth); + var converter = new KitchenReceiptConverterKlinglers(_lineWidth, _bigFontLineWidth); return converter.ConvertToPrintCommands(receipt); } } diff --git a/Inspectron.Epson/PrintServer/Printers/Utils/KitchenReceipt/KitchenReceiptConverterKlinglers.cs b/Inspectron.Epson/PrintServer/Printers/Utils/KitchenReceipt/KitchenReceiptConverterKlinglers.cs new file mode 100644 index 0000000..9cc510c --- /dev/null +++ b/Inspectron.Epson/PrintServer/Printers/Utils/KitchenReceipt/KitchenReceiptConverterKlinglers.cs @@ -0,0 +1,247 @@ +namespace Inspectron.Epson.PrintServer.Printers.Utils.KitchenReceipt; + +public class KitchenReceiptConverterKlinglers +{ + private readonly int _lineWidth; + private readonly int _BigLineWidth; + + public KitchenReceiptConverterKlinglers(int lineWidth = 42, int bigLineWidth = 22) + { + _BigLineWidth = bigLineWidth; + _lineWidth = lineWidth; + } + + public List ConvertToPrintCommands(KitchenReceipt kitchenReceipt) + { + var commands = new List(); + + // Header - Restaurant name in red + commands.Add(new PrintCommand(Center(kitchenReceipt.Title, true)) { IsRed = true, IsBig = true, IsTall = true }); + commands.Add(new PrintCommand(CreateDashedLine())); + commands.Add(new PrintCommand("")); + + // Transaction info + string dateTimeLine = $"{kitchenReceipt.TransactionDateTime:dd-MMM-yy HH:mm} Nr.:{kitchenReceipt.ReceiptNumber}"; + commands.Add(new PrintCommand(Center(dateTimeLine, false))); + + string serverLine = $"{kitchenReceipt.WaiterName}"; + commands.Add(new PrintCommand(Center(serverLine, false))); + + //string serverIdLine = $"{kitchenReceipt.WaiterId}"; + //commands.Add(new PrintCommand(Center(serverIdLine, false))); + + string tableLine = $"Tisch: {kitchenReceipt.TableNumber}"; + commands.Add(new PrintCommand(Center(tableLine, true), true, true)); + + if (!string.IsNullOrEmpty(kitchenReceipt.SpecialInstruction)) + { + commands.Add(new PrintCommand("")); + commands.Add(new PrintCommand(Center(kitchenReceipt.SpecialInstruction, true), true, true)); + commands.Add(new PrintCommand("")); + } + + commands.Add(new PrintCommand(CreateDashedLine())); + + + + + // Gangs + + foreach (Gang gang in kitchenReceipt.Gangs) + { + + commands.Add(new PrintCommand(Center($"{gang.Id}. {gang.Name}", true)) { IsRed = true, IsBig = true, IsTall = true }); + PrintGroupedDishes(gang.Dishes, commands); + + if (gang != kitchenReceipt.Gangs.Last()) + { + commands.Add(new PrintCommand("") { IsCut = true }); + commands.Add(new PrintCommand("")); + commands.Add(new PrintCommand("")); + } + } + + if (kitchenReceipt.Gangs.Count > 0) + { + commands.Add(new PrintCommand(CreateDashedLine())); + } + + PrintGroupedDishes(kitchenReceipt.Dishes, commands); + + if (kitchenReceipt.Dishes != null && kitchenReceipt.Dishes.Any()) + { + commands.Add(new PrintCommand("")); + commands.Add(new PrintCommand(CreateDashedLine())); + commands.Add(new PrintCommand("")); + } + + + //// Additional info section + //if (kitchenReceipt.AdditionalInfo != null && kitchenReceipt.AdditionalInfo.Count > 0) + //{ + // commands.Add(new PrintCommand(CreateAsterisksLine())); + // commands.Add(new PrintCommand("Info über zugehörige Artikel")); + // commands.Add(new PrintCommand(CreateAsterisksLine())); + + // foreach (var info in kitchenReceipt.AdditionalInfo) + // { + // commands.Add(new PrintCommand(info)); + // } + + // commands.Add(new PrintCommand("")); + //} + + return commands; + } + + private static bool IsGroupable(Dish dish) + { + 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; + return true; + } + + private void PrintGroupedDishes(List dishes, List commands) + { + var groupable = dishes.Where(IsGroupable).ToList(); + var individual = dishes.Where(d => !IsGroupable(d)).ToList(); + + // Print grouped dishes + var groups = groupable + .GroupBy(d => d.Name) + .ToList(); + + foreach (var group in groups) + { + int totalQuantity = group.Sum(d => d.Number); + var guestIds = group + .Where(d => d.GuestId.HasValue) + .Select(d => d.GuestId.Value) + .OrderBy(id => id) + .ToList(); + + PrintDishLine($"{totalQuantity}x ", group.Key, null, commands); + + if (guestIds.Any()) + { + string guestLine = $"({string.Join(",", guestIds)})"; + commands.Add(new PrintCommand(guestLine, isBold: true) { IsTall = true }); + } + } + + // Print individual dishes (have size, modifications, or comment) + foreach (var dish in individual) + { + PrintDishLine($"{dish.Number}x ", dish.Name, dish.Size, commands); + + if (dish.GuestId.HasValue) + { + string guestLine = $"({dish.GuestId.Value})"; + commands.Add(new PrintCommand(guestLine, isBold: true) { IsTall = true }); + } + + if (dish.Modifications != null && (dish.Modifications.Removed.Any() || dish.Modifications.Added.Any())) + { + foreach (var removed in dish.Modifications.Removed) + { + commands.Add(new PrintCommand($" - {removed}", isBold: true) { IsTall = true }); + } + foreach (var added in dish.Modifications.Added) + { + commands.Add(new PrintCommand($" + {added}", isBold: true) { IsTall = true }); + } + } + + if (!string.IsNullOrEmpty(dish.Comment)) + { + commands.Add(new PrintCommand($"Comment: {dish.Comment}", isBold: true) { IsTall = true }); + } + } + } + + private void PrintDishLine(string quantityPrefix, string dishName, string? size, List commands) + { + string fullLine = quantityPrefix + dishName; + + if (!string.IsNullOrEmpty(size)) + { + fullLine += $" ({size})"; + } + + if (fullLine.Length <= _lineWidth || string.IsNullOrEmpty(dishName)) + { + commands.Add(new PrintCommand(fullLine) { IsTall = true }); + } + else + { + int availableWidth = _lineWidth - quantityPrefix.Length; + if (availableWidth <= 0) + { + commands.Add(new PrintCommand(fullLine) { IsTall = true }); + } + else + { + string nameWithSize = dishName; + if (!string.IsNullOrEmpty(size)) + { + nameWithSize += $" ({size})"; + } + var words = nameWithSize.Split(' '); + var lines = new List(); + 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 }); + } + } + } + } + + private string Center(string text, bool isBigFont) + { + var actualLineWidth = isBigFont ? _BigLineWidth : _lineWidth; + if (string.IsNullOrEmpty(text) || text.Length >= actualLineWidth) + return text; + + int totalPadding = actualLineWidth - text.Length; + int leftPadding = totalPadding / 2; + + return new string(' ', leftPadding) + text; + } + + private string CreateDashedLine() + { + return new string('-', _lineWidth); + } + + private string CreateAsterisksLine() + { + return new string('*', _lineWidth); + } +} \ No newline at end of file