diff --git a/EpsonPrintService/PrinterDiscoveryBackgroundTask.cs b/EpsonPrintService/PrinterDiscoveryBackgroundTask.cs index 69e41f4..3852e21 100644 --- a/EpsonPrintService/PrinterDiscoveryBackgroundTask.cs +++ b/EpsonPrintService/PrinterDiscoveryBackgroundTask.cs @@ -12,6 +12,7 @@ public class PrinterDiscoveryBackgroundTask private readonly IDiscoveryService _discoveryService; private readonly IDiscoveredPrintersReceiver _receiver; private readonly ILogger _logger; + private readonly PrintServer _printServer; private readonly TimeSpan _interval; private readonly TimeSpan _discoveryTimeout; @@ -21,11 +22,13 @@ public class PrinterDiscoveryBackgroundTask public PrinterDiscoveryBackgroundTask( IDiscoveryService discoveryService, IDiscoveredPrintersReceiver receiver, - ILogger logger) + ILogger logger, + PrintServer printServer) { _discoveryService = discoveryService; _receiver = receiver; _logger = logger; + _printServer = printServer; _interval = TimeSpan.FromSeconds(30); _discoveryTimeout = TimeSpan.FromSeconds(3); } @@ -67,13 +70,14 @@ public class PrinterDiscoveryBackgroundTask try { var printers = await _discoveryService.DiscoverPrintersAsync(_discoveryTimeout); - printers.Add(new DiscoveredPrinter() - { - IPAddress = "127.0.0.1", - ModelName = "TM-T30III", - }); + var currentIps = printers.Select(p => p.IPAddress).ToHashSet(); + foreach (string currentIp in currentIps) + { + _printServer.RegisterPrinter(currentIp); + } + if (HasConfigurationChanged(currentIps)) { _logger.LogInformation("Discovered printer configuration changed: {Count} printer(s)", printers.Count); diff --git a/EpsonPrintService/Program.cs b/EpsonPrintService/Program.cs index 92e8685..c83fa85 100644 --- a/EpsonPrintService/Program.cs +++ b/EpsonPrintService/Program.cs @@ -10,6 +10,7 @@ using Inspectron.Epson.PrintServer.ConfigurationSources; using Inspectron.Epson.PrintServer.JobSources; using Inspectron.Epson.PrintServer.PrinterAssinment; using Inspectron.Epson.PrintServer.Printers; +using Inspectron.Epson.PrintServer.Printers.Utils; using Inspectron.Epson.PrintServer.PrintServices; using EpsonPrintService; @@ -40,6 +41,7 @@ kernel.Bind().ToMethod(ctx => kernel.Bind().ToConstant(config); kernel.Bind().To().InSingletonScope(); kernel.Bind().To(); +kernel.Bind().To().InSingletonScope(); kernel.Bind().ToSelf().InSingletonScope(); kernel.Bind().To().InSingletonScope(); kernel.Bind().ToSelf().InSingletonScope(); diff --git a/EpsonPrintService/config.json b/EpsonPrintService/config.json index b6ee866..fe92084 100644 --- a/EpsonPrintService/config.json +++ b/EpsonPrintService/config.json @@ -1,6 +1,6 @@ { - "GroupId": "64a3d9f0876bc5d1704bce43", - "RestaurantId": "64a3d9f0876bc5d1704bce43", - "ApiKey": "LBOACMlvFEgDbZqt24uW0LjiFv0LKU5DT94g0JDoBnI=", + "GroupId": "63e37295bd6f26dbd36164c0", + "RestaurantId": "63e37295bd6f26dbd36164c0", + "ApiKey": "Pd8X/VtXLWgl5Djy4ksjdHC3xboeoh5Jig3Qo4277GQ=", "PrinterConfigurations": {} } \ No newline at end of file diff --git a/EpsonTest/Program.cs b/EpsonTest/Program.cs index 575fb3d..1bf2ce4 100644 --- a/EpsonTest/Program.cs +++ b/EpsonTest/Program.cs @@ -8,6 +8,7 @@ using SixLabors.ImageSharp.PixelFormats; using System.Text; using System.Text.Json; using System.Xml.Linq; +using Inspectron.Epson.PrintServer.Printers.Utils.FinalReceipt; using Inspectron.Epson.PrintServer.Printers.Utils.OrderItems; using FinalReceipt = Inspectron.Epson.PrintServer.Printers.Utils.FinalRecipe.FinalReceipt; @@ -189,8 +190,8 @@ using FinalReceipt = Inspectron.Epson.PrintServer.Printers.Utils.FinalRecipe.Fin //var serializedReceipt = JsonSerializer.Serialize(receipt, new JsonSerializerOptions { WriteIndented = true }); //var deserializedReceipt = JsonSerializer.Deserialize(serializedReceipt); //// Convert to print commands -//var converter = new ReceiptConverter(lineWidth: 48, bigFontLineWidth: 24); -//var printCommands = converter.ConvertToPrintCommands(deserializedReceipt); +//var converter = new FinalReceiptConverter(lineWidth: 48, bigFontLineWidth: 24); +//var printCommands = converter.Convert(serializedReceipt); @@ -248,10 +249,32 @@ using FinalReceipt = Inspectron.Epson.PrintServer.Printers.Utils.FinalRecipe.Fin //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") +//{ +// Modifications = new DishModifications +// { +// Removed = new List { "Wasabi" }, +// Added = new List { "Extra Ginger" } +// }, +// Comment = "No soy sauce" +//}); //receipt.Gangs[0].Dishes.Add(new Dish(1, "Baby Spinach Salad with Truffl")); -//receipt.Gangs[0].Dishes.Add(new Dish(1, "Beef Tataki")); -//receipt.Gangs[0].Dishes.Add(new Dish(1, "Salmon Taco")); +//receipt.Gangs[0].Dishes.Add(new Dish(1, "Beef Tataki") +//{ +// Modifications = new DishModifications +// { +// Removed = new List { "Onion" }, +// Added = new List { "Extra Sauce" } +// }, +// Comment = "Medium rare" +//}); +//receipt.Gangs[0].Dishes.Add(new Dish(1, "Salmon Taco") +//{ +// Modifications = new DishModifications +// { +// Added = new List { "Extra Lime" } +// } +//}); //receipt.Gangs[1].Dishes.Add(new Dish(1, "Avocado Sashimi")); @@ -308,11 +331,98 @@ using FinalReceipt = Inspectron.Epson.PrintServer.Printers.Utils.FinalRecipe.Fin //} + +var receipt = new KitchenReceipt +{ + Title = "Warme Küche", + TransactionDateTime = new DateTime(2025, 10, 23, 12, 18, 0), + ReceiptNumber = "132018166", + WaiterName = "Mariano Amato", + WaiterId = "32 (VK Restaurant)", + TableNumber = "22", + SpecialInstruction = "Next dish" +}; + +// Add dishes (this section can be empty if no dishes were ordered) + +receipt.Gangs.Add(new Gang(2, "Gang")); + +receipt.Gangs[0].Dishes.Add(new Dish(1, "Avocado Sashimi") +{ + Modifications = new DishModifications + { + Removed = new List { "Wasabi" }, + Added = new List { "Extra Ginger" } + }, + Comment = "No soy sauce" +}); +receipt.Gangs[0].Dishes.Add(new Dish(1, "Baby Spinach Salad with Truffl")); +receipt.Gangs[0].Dishes.Add(new Dish(1, "Beef Tataki") +{ + Modifications = new DishModifications + { + Removed = new List { "Onion" }, + Added = new List { "Extra Sauce" } + }, + Comment = "Medium rare" +}); +receipt.Gangs[0].Dishes.Add(new Dish(1, "Salmon Taco") +{ + Modifications = new DishModifications + { + Added = new List { "Extra Lime" } + } +}); + +// Add additional info + +var serializedReceipt = JsonSerializer.Serialize(receipt, new JsonSerializerOptions { WriteIndented = true }); +var deserializedReceipt = JsonSerializer.Deserialize(serializedReceipt); +KitchenReceiptConverter converter = new KitchenReceiptConverter(bigLineWidth: 20, lineWidth: 33); +var printCommands = converter.ConvertToPrintCommands(deserializedReceipt); + +Console.WriteLine("=== PRINT COMMANDS ===\n"); +var printer = new HtmlPrinter(@".\test.html", paperWidth: 258); +await printer.ConnectAsync(""); +await Task.Delay(200); +await printer.FeedLinesAsync(1); +await printer.SetCustomLineSpacing(22); +foreach (var command in printCommands) +{ + string attributes = ""; + if (command.IsBig) attributes += "[BIG] "; + if (command.IsBold) attributes += "[BOLD] "; + if (command.IsRed) attributes += "[RED] "; + + Console.WriteLine($"{attributes}{command.Text}"); + + if (command.IsBig) + { + await printer.SetFontSizeAsync(2, 1); + } + else + { + await printer.SetFontSizeAsync(1, 1); + } + + await printer.SetRedColor(command.IsRed); + + //await Task.Delay(200); + + await printer.SetEmphasized(command.IsBold); + //await Task.Delay(200); + + await printer.PrintTextAsync(command.Text + "\n"); + //await Task.Delay(200); + +} + + //await printer.SetDefaultLineSpacing(); //await printer.PrintTextAsync( // "1x San Pellegrino 50cl 6.50 6.50 A\n1x Panna 50cl 6.50 6.50 A"); -// Order Items Receipt Test +//// Order Items Receipt Test //var orderItemsReceipt = new OrderItemsReceipt //{ // OrderNumber = "1", diff --git a/Inspectron.Epson/PrintServer/PrintServices/EpsonPrintService.cs b/Inspectron.Epson/PrintServer/PrintServices/EpsonPrintService.cs index dc9f83d..a9efa37 100644 --- a/Inspectron.Epson/PrintServer/PrintServices/EpsonPrintService.cs +++ b/Inspectron.Epson/PrintServer/PrintServices/EpsonPrintService.cs @@ -1,6 +1,6 @@ -using Microsoft.Extensions.Logging; -using System.Reflection; +using Microsoft.Extensions.Logging; using Inspectron.Epson.PrintServer.Printers; +using Inspectron.Epson.PrintServer.Printers.Utils; namespace Inspectron.Epson.PrintServer.PrintServices; @@ -10,13 +10,15 @@ public class EpsonPrintService: IPrintService private readonly IPrinterFactory _printerFactory; private readonly IWrapperPrinterFactory _wrapperPrinterFactory; private readonly IPrinterConfigurationSource _printerConfigurationSource; + private readonly IReceiptConverterFactory _receiptConverterFactory; - public EpsonPrintService(ILogger logger, IPrinterFactory printerFactory, IWrapperPrinterFactory wrapperPrinterFactory, IPrinterConfigurationSource printerConfigurationSource) + public EpsonPrintService(ILogger logger, IPrinterFactory printerFactory, IWrapperPrinterFactory wrapperPrinterFactory, IPrinterConfigurationSource printerConfigurationSource, IReceiptConverterFactory receiptConverterFactory) { _logger = logger; _printerFactory = printerFactory; _wrapperPrinterFactory = wrapperPrinterFactory; _printerConfigurationSource = printerConfigurationSource; + _receiptConverterFactory = receiptConverterFactory; } public async Task PrintAsync(string printerIp, PrintJob job) @@ -25,19 +27,8 @@ public class EpsonPrintService: IPrintService { var configuration = _printerConfigurationSource.GetConfiguration(printerIp); await using var epsonPrinter = _printerFactory.CreatePrinter(); - string address; + string address = printerIp; int port = 9100; - var printerAddress = configuration.Address; - if (printerAddress.Contains(":")) - { - var parts = printerAddress.Split(':'); - address = parts[0]; - port = int.Parse(parts[1]); - } - else - { - address = printerAddress; - } await epsonPrinter.ConnectAsync(address, port); @@ -90,7 +81,10 @@ public class EpsonPrintService: IPrintService await printerAdapter.SetFontSizeAsync(configuration.FontSize); - await printerAdapter.PrintTextAsync(job.Document.Content); + // Convert receipt content to print commands using the factory + var converter = _receiptConverterFactory.Create(job.Document.ReceiptType, lineWidth: 48, bigFontLineWidth: 24); + var commands = converter.Convert(job.Document.Content); + await printerAdapter.PrintAsync(commands); await Task.Delay(200); status = await epsonPrinter.GetPrinterStatusAsync(); if (!status.IsOnline) diff --git a/Inspectron.Epson/PrintServer/PrintServices/IPrinter.cs b/Inspectron.Epson/PrintServer/PrintServices/IPrinter.cs index c0b9890..296e07a 100644 --- a/Inspectron.Epson/PrintServer/PrintServices/IPrinter.cs +++ b/Inspectron.Epson/PrintServer/PrintServices/IPrinter.cs @@ -1,10 +1,12 @@ -namespace Inspectron.Epson.PrintServer.PrintServices; +using Inspectron.Epson.PrintServer.Printers.Utils; + +namespace Inspectron.Epson.PrintServer.PrintServices; public interface IPrinter { public Task InitAsync(); public Task PrintImageAsync(string path); public Task SetFontSizeAsync(int fontSize); - public Task PrintTextAsync(string text); + public Task PrintAsync(List commands); public Task Cut(); } \ No newline at end of file diff --git a/Inspectron.Epson/PrintServer/Printers/TM-T30III.cs b/Inspectron.Epson/PrintServer/Printers/TM-T30III.cs index d373dac..af8c9f2 100644 --- a/Inspectron.Epson/PrintServer/Printers/TM-T30III.cs +++ b/Inspectron.Epson/PrintServer/Printers/TM-T30III.cs @@ -1,10 +1,9 @@ -using Inspectron.Epson.PrintServer.PrintServices; -using System.Net.NetworkInformation; -using System.Reflection; +using Inspectron.Epson.PrintServer.Printers.Utils; +using Inspectron.Epson.PrintServer.PrintServices; namespace Inspectron.Epson.PrintServer.Printers; -public class TM_T30III:IPrinter +public class TM_T30III : IPrinter { private readonly EpsonPrinter _printer; @@ -33,11 +32,25 @@ public class TM_T30III:IPrinter await _printer.SetFontSizeAsync(fontSize, fontSize); } - public async Task PrintTextAsync(string text) + public async Task PrintAsync(List commands) { - await _printer.PrintTextAsync(text); + foreach (var command in commands) + { + if (command.IsBig) + { + await _printer.SetFontSizeAsync(2, 2); + } + else + { + await _printer.SetFontSizeAsync(1, 1); + } + + await _printer.SetRedColor(command.IsRed); + await _printer.SetEmphasized(command.IsBold); + await _printer.PrintTextAsync(command.Text + "\n"); + } + await _printer.FeedLinesAsync(5); - var status = await _printer.GetPrinterStatusAsync(); } public async Task Cut() diff --git a/Inspectron.Epson/PrintServer/Printers/TM-T30IIITranslated.cs b/Inspectron.Epson/PrintServer/Printers/TM-T30IIITranslated.cs index 63e3e7f..bf657ae 100644 --- a/Inspectron.Epson/PrintServer/Printers/TM-T30IIITranslated.cs +++ b/Inspectron.Epson/PrintServer/Printers/TM-T30IIITranslated.cs @@ -1,13 +1,9 @@ -using Inspectron.Epson.PrintServer.Printers.Utils; -using Inspectron.Epson.PrintServer.Printers.Utils.FinalRecipe; +using Inspectron.Epson.PrintServer.Printers.Utils; using Inspectron.Epson.PrintServer.PrintServices; -using System.Reflection; -using System.Text.Json; -using FinalReceipt = Inspectron.Epson.PrintServer.Printers.Utils.FinalRecipe.FinalReceipt; namespace Inspectron.Epson.PrintServer.Printers; -public class TM_T30IIITranslated:IPrinter +public class TM_T30IIITranslated : IPrinter { private readonly IEpsonPrinter _printer; @@ -40,31 +36,12 @@ public class TM_T30IIITranslated:IPrinter //await _printer.SetFontSizeAsync(fontSize, fontSize); } - public async Task PrintTextAsync(string text) + public async Task PrintAsync(List commands) { - FinalReceipt? receipt; - try - { - receipt = JsonSerializer.Deserialize(text); - } - catch - { - // Fallback to kitchen receipt - await PrintKitchen(text); - return; - } - var converter = new ReceiptConverter(lineWidth: 48, bigFontLineWidth: 24); - var printCommands = converter.ConvertToPrintCommands(receipt); await _printer.SetCustomLineSpacing(22); - foreach (var command in printCommands) + foreach (var command in commands) { - string attributes = ""; - if (command.IsBig) attributes += "[BIG]\n"; - if (command.IsBold) attributes += "[BOLD]\n"; - - Console.WriteLine($"{attributes}{command.Text}"); - if (command.IsBig) { await _printer.SetFontSizeAsync(2, 1); @@ -73,11 +50,11 @@ public class TM_T30IIITranslated:IPrinter { await _printer.SetFontSizeAsync(1, 1); } - - await _printer.SetEmphasized(command.IsBold); - - await _printer.PrintTextAsync(command.Text + "\n"); + + await _printer.SetRedColor(command.IsRed); + await _printer.SetEmphasized(command.IsBold); + await _printer.PrintTextAsync(command.Text + "\n"); } await _printer.SetDefaultLineSpacing(); @@ -85,37 +62,6 @@ public class TM_T30IIITranslated:IPrinter await Task.Delay(200); } - private async Task PrintKitchen(string text) - { - ReceiptTranslator translator = new ReceiptTranslator(); - var ast = translator.ParseReceipt(text); - KitchenReceiptPrinter printer = new KitchenReceiptPrinter(lineWidth: 33, 21); - var commands = printer.ConvertToCommands((TranslatedKitchenReceipt)ast); - foreach (KitchenPrintCommand command in commands) - { - if (command.IsBig) - { - await _printer.SetFontSizeAsync(2,2); - } - else - { - await _printer.SetFontSizeAsync(1, 1); - } - - - await Task.Delay(200); - await _printer.SetRedColor(command.IsRed); - await Task.Delay(200); - await _printer.SetEmphasized(command.IsBold); - await Task.Delay(200); - await _printer.PrintTextAsync(command.Text + "\n"); - await Task.Delay(200); - } - - await _printer.FeedLinesAsync(10); - await Task.Delay(1000); - } - public async Task Cut() { await _printer.CutAsync(); diff --git a/Inspectron.Epson/PrintServer/Printers/TM-U220II.cs b/Inspectron.Epson/PrintServer/Printers/TM-U220II.cs index 59b6759..63d038c 100644 --- a/Inspectron.Epson/PrintServer/Printers/TM-U220II.cs +++ b/Inspectron.Epson/PrintServer/Printers/TM-U220II.cs @@ -1,9 +1,9 @@ -using Inspectron.Epson.PrintServer.PrintServices; -using System.Reflection; +using Inspectron.Epson.PrintServer.Printers.Utils; +using Inspectron.Epson.PrintServer.PrintServices; namespace Inspectron.Epson.PrintServer.Printers; -public class TM_U220II:IPrinter +public class TM_U220II : IPrinter { private readonly EpsonPrinter _printer; @@ -31,14 +31,20 @@ public class TM_U220II:IPrinter await Task.Delay(200); } - public async Task PrintTextAsync(string text) + public async Task PrintAsync(List commands) { - await _printer.PrintTextAsync(text); - var lines = text.Split('\n').Length; - for (int i = 0; i < lines; i++) + foreach (var command in commands) { + await _printer.SetBiggerFontTM220(command.IsBig); + await Task.Delay(200); + await _printer.SetRedColor(command.IsRed); + await Task.Delay(200); + await _printer.SetEmphasized(command.IsBold); + await Task.Delay(200); + await _printer.PrintTextAsync(command.Text + "\n"); await Task.Delay(200); } + await _printer.FeedLinesAsync(5); await Task.Delay(200); } diff --git a/Inspectron.Epson/PrintServer/Printers/TM-U220IITranslated.cs b/Inspectron.Epson/PrintServer/Printers/TM-U220IITranslated.cs index 34259c5..3d1d89c 100644 --- a/Inspectron.Epson/PrintServer/Printers/TM-U220IITranslated.cs +++ b/Inspectron.Epson/PrintServer/Printers/TM-U220IITranslated.cs @@ -1,12 +1,9 @@ -using Inspectron.Epson.PrintServer.Printers.Utils; -using Inspectron.Epson.PrintServer.Printers.Utils.KitchenReceipt; +using Inspectron.Epson.PrintServer.Printers.Utils; using Inspectron.Epson.PrintServer.PrintServices; -using System.Reflection; -using System.Text.Json; namespace Inspectron.Epson.PrintServer.Printers; -public class TM_U220IITranslated:IPrinter +public class TM_U220IITranslated : IPrinter { private readonly IEpsonPrinter _printer; @@ -34,11 +31,8 @@ public class TM_U220IITranslated:IPrinter //await Task.Delay(200); } - public async Task PrintTextAsync(string text) + public async Task PrintAsync(List commands) { - var deserializedReceipt = JsonSerializer.Deserialize(text); - KitchenReceiptConverter translator = new KitchenReceiptConverter(bigLineWidth: 20, lineWidth: 33); - var commands = translator.ConvertToPrintCommands(deserializedReceipt); foreach (var command in commands) { await _printer.SetBiggerFontTM220(command.IsBig); @@ -50,7 +44,7 @@ public class TM_U220IITranslated:IPrinter await _printer.PrintTextAsync(command.Text + "\n"); await Task.Delay(200); } - + await _printer.FeedLinesAsync(10); await Task.Delay(1000); } diff --git a/Inspectron.Epson/PrintServer/Printers/Utils/FinalReceipt/FinalReceiptConverter.cs b/Inspectron.Epson/PrintServer/Printers/Utils/FinalReceipt/FinalReceiptConverter.cs new file mode 100644 index 0000000..27553c3 --- /dev/null +++ b/Inspectron.Epson/PrintServer/Printers/Utils/FinalReceipt/FinalReceiptConverter.cs @@ -0,0 +1,22 @@ +using System.Text.Json; + +namespace Inspectron.Epson.PrintServer.Printers.Utils.FinalReceipt; + +public class FinalReceiptConverter : IReceiptConverter +{ + private readonly int _lineWidth; + private readonly int _bigFontLineWidth; + + public FinalReceiptConverter(int lineWidth, int bigFontLineWidth) + { + _lineWidth = lineWidth; + _bigFontLineWidth = bigFontLineWidth; + } + + public List Convert(string jsonContent) + { + var receipt = JsonSerializer.Deserialize(jsonContent); + var converter = new FinalRecipe.ReceiptConverter(_lineWidth, _bigFontLineWidth); + return converter.ConvertToPrintCommands(receipt); + } +} diff --git a/Inspectron.Epson/PrintServer/Printers/Utils/IReceiptConverter.cs b/Inspectron.Epson/PrintServer/Printers/Utils/IReceiptConverter.cs new file mode 100644 index 0000000..59acb64 --- /dev/null +++ b/Inspectron.Epson/PrintServer/Printers/Utils/IReceiptConverter.cs @@ -0,0 +1,6 @@ +namespace Inspectron.Epson.PrintServer.Printers.Utils; + +public interface IReceiptConverter +{ + List Convert(string jsonContent); +} diff --git a/Inspectron.Epson/PrintServer/Printers/Utils/IReceiptConverterFactory.cs b/Inspectron.Epson/PrintServer/Printers/Utils/IReceiptConverterFactory.cs new file mode 100644 index 0000000..6cfe843 --- /dev/null +++ b/Inspectron.Epson/PrintServer/Printers/Utils/IReceiptConverterFactory.cs @@ -0,0 +1,6 @@ +namespace Inspectron.Epson.PrintServer.Printers.Utils; + +public interface IReceiptConverterFactory +{ + IReceiptConverter Create(int receiptType, int lineWidth, int bigFontLineWidth); +} diff --git a/Inspectron.Epson/PrintServer/Printers/Utils/KitchenPrintCommand.cs b/Inspectron.Epson/PrintServer/Printers/Utils/KitchenPrintCommand.cs deleted file mode 100644 index 8ca0c69..0000000 --- a/Inspectron.Epson/PrintServer/Printers/Utils/KitchenPrintCommand.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Inspectron.Epson.PrintServer.Printers.Utils; - -public class KitchenPrintCommand -{ - public bool IsBig { get; set; } - public bool IsBold { get; set; } - public bool IsRed { get; set; } - public string Text { get; set; } -} \ No newline at end of file diff --git a/Inspectron.Epson/PrintServer/Printers/Utils/KitchenReceipt/KitchenReceiptConverter.cs b/Inspectron.Epson/PrintServer/Printers/Utils/KitchenReceipt/KitchenReceiptConverter.cs index 1ebb2f1..83a8f56 100644 --- a/Inspectron.Epson/PrintServer/Printers/Utils/KitchenReceipt/KitchenReceiptConverter.cs +++ b/Inspectron.Epson/PrintServer/Printers/Utils/KitchenReceipt/KitchenReceiptConverter.cs @@ -33,6 +33,13 @@ public class KitchenReceiptConverter 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())); @@ -46,8 +53,7 @@ public class KitchenReceiptConverter commands.Add(new PrintCommand(Center($"{gang.Id}. {gang.Name}", false)) { IsRed = true }); foreach (var dish in gang.Dishes) { - string dishLine = $"{dish.Number}x {dish.Name}"; - commands.Add(new PrintCommand(dishLine)); + PrintDish(dish, commands); } } @@ -58,15 +64,17 @@ public class KitchenReceiptConverter foreach (var dish in kitchenReceipt.Dishes) { - string dishLine = $"{dish.Number}x {dish.Name}"; - commands.Add(new PrintCommand(dishLine)); + PrintDish(dish, commands); + } + + if (kitchenReceipt.Dishes != null && kitchenReceipt.Dishes.Any()) + { + commands.Add(new PrintCommand("")); + commands.Add(new PrintCommand(CreateDashedLine())); + commands.Add(new PrintCommand("")); } - commands.Add(new PrintCommand("")); - commands.Add(new PrintCommand(CreateDashedLine())); - commands.Add(new PrintCommand("")); - //// Additional info section //if (kitchenReceipt.AdditionalInfo != null && kitchenReceipt.AdditionalInfo.Count > 0) //{ @@ -85,6 +93,33 @@ public class KitchenReceiptConverter return commands; } + private static void PrintDish(Dish dish, List commands) + { + string dishLine = $"{dish.Number}x {dish.Name}"; + commands.Add(new PrintCommand(dishLine)); + // Modifications + 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)); + } + + foreach (var added in dish.Modifications.Added) + { + commands.Add(new PrintCommand($" + {added}", isBold: true)); + } + } + + // SpecialInstruction + if (!string.IsNullOrEmpty(dish.Comment)) + { + commands.Add(new PrintCommand($" Comment: {dish.Comment}", isBold: true)); + } + + //commands.Add(new PrintCommand($"")); + } + private string Center(string text, bool isBigFont) { var actualLineWidth = isBigFont ? _BigLineWidth : _lineWidth; diff --git a/Inspectron.Epson/PrintServer/Printers/Utils/KitchenReceipt/KitchenReceiptConverterAdapter.cs b/Inspectron.Epson/PrintServer/Printers/Utils/KitchenReceipt/KitchenReceiptConverterAdapter.cs new file mode 100644 index 0000000..2f8e94f --- /dev/null +++ b/Inspectron.Epson/PrintServer/Printers/Utils/KitchenReceipt/KitchenReceiptConverterAdapter.cs @@ -0,0 +1,22 @@ +using System.Text.Json; + +namespace Inspectron.Epson.PrintServer.Printers.Utils.KitchenReceipt; + +public class KitchenReceiptConverterAdapter : IReceiptConverter +{ + private readonly int _lineWidth; + private readonly int _bigFontLineWidth; + + public KitchenReceiptConverterAdapter(int lineWidth, int bigFontLineWidth) + { + _lineWidth = lineWidth; + _bigFontLineWidth = bigFontLineWidth; + } + + public List Convert(string jsonContent) + { + var receipt = JsonSerializer.Deserialize(jsonContent); + var converter = new KitchenReceiptConverter(_lineWidth, _bigFontLineWidth); + return converter.ConvertToPrintCommands(receipt); + } +} diff --git a/Inspectron.Epson/PrintServer/Printers/Utils/KitchenReceipt/Models.cs b/Inspectron.Epson/PrintServer/Printers/Utils/KitchenReceipt/Models.cs index 2f22719..00bafed 100644 --- a/Inspectron.Epson/PrintServer/Printers/Utils/KitchenReceipt/Models.cs +++ b/Inspectron.Epson/PrintServer/Printers/Utils/KitchenReceipt/Models.cs @@ -33,8 +33,9 @@ /// /// Table number /// - public int TableNumber { get; set; } + public string TableNumber { get; set; } + public string SpecialInstruction { get; set; } public List Gangs { get; set; } = new List(); @@ -77,12 +78,22 @@ /// public string Name { get; set; } + public Dish(){} + public Dish(int number, string name) { Number = number; Name = name; } + + public DishModifications Modifications { get; set; } = new DishModifications(); + public string? Comment { get; set; } + } + + public class DishModifications + { + public List Removed { get; set; } = new List(); + public List Added { get; set; } = new List(); } - } \ No newline at end of file diff --git a/Inspectron.Epson/PrintServer/Printers/Utils/KitchenReceiptPrinter.cs b/Inspectron.Epson/PrintServer/Printers/Utils/KitchenReceiptPrinter.cs deleted file mode 100644 index 8cbec8c..0000000 --- a/Inspectron.Epson/PrintServer/Printers/Utils/KitchenReceiptPrinter.cs +++ /dev/null @@ -1,95 +0,0 @@ -namespace Inspectron.Epson.PrintServer.Printers.Utils; - -public class KitchenReceiptPrinter -{ - private readonly int _lineWidth; - private readonly int _bigFontLineWidth; - - public KitchenReceiptPrinter(int lineWidth = 42, int bigFontLineWidth = 21) - { - _lineWidth = lineWidth; - _bigFontLineWidth = bigFontLineWidth; - } - - public List ConvertToCommands(TranslatedKitchenReceipt receipt) - { - var commands = new List(); - - // Header: "Warme Küche" - Big, Bold, Red, Centered - commands.Add(new KitchenPrintCommand - { - Text = Center(receipt.Location, isBigFont: true), - IsBig = true, - IsBold = true, - IsRed = true - }); - - commands.Add(Separator()); - - // Date and Owner info - Normal, Left-aligned - commands.Add(new KitchenPrintCommand { Text = Center(receipt.Date,false) }); - var ownerLines = receipt.Owner.Split('\n'); - foreach (var line in ownerLines) - { - commands.Add(new KitchenPrintCommand { Text = Center(line, false) }); - } - - // Table number - Big, Bold, Centered - commands.Add(new KitchenPrintCommand - { - Text = Center($"Tisch: {receipt.Tisch}", isBigFont: true), - IsBig = true, - IsBold = true - }); - - commands.Add(Separator()); - - // Items - Left-aligned - foreach (var item in receipt.items) - { - if (item is KitchenProduct kp) - { - commands.Add(new KitchenPrintCommand - { - Text = $"{kp.Amount}x {item.Name}" - }); - } - if(item is KitchenGang kg) - { - commands.Add(new KitchenPrintCommand - { - IsRed = true, - IsBig = true, - IsBold = true, - Text = Center(item.Name,true) - }); - } - - } - - commands.Add(Separator()); - - return commands; - } - - private KitchenPrintCommand Separator() - { - return new KitchenPrintCommand - { - Text = new string('-', _lineWidth) - }; - } - - private string Center(string text, bool isBigFont) - { - int effectiveLineWidth = isBigFont ? _bigFontLineWidth : _lineWidth; - - if (string.IsNullOrEmpty(text) || text.Length >= effectiveLineWidth) - return text; - - int totalPadding = effectiveLineWidth - text.Length; - int leftPadding = totalPadding / 2; - - return new string(' ', leftPadding) + text; - } -} \ No newline at end of file diff --git a/Inspectron.Epson/PrintServer/Printers/Utils/OrderItems/OrderItemsReceiptConverter.cs b/Inspectron.Epson/PrintServer/Printers/Utils/OrderItems/OrderItemsReceiptConverter.cs new file mode 100644 index 0000000..2ef933c --- /dev/null +++ b/Inspectron.Epson/PrintServer/Printers/Utils/OrderItems/OrderItemsReceiptConverter.cs @@ -0,0 +1,22 @@ +using System.Text.Json; + +namespace Inspectron.Epson.PrintServer.Printers.Utils.OrderItems; + +public class OrderItemsReceiptConverter : IReceiptConverter +{ + private readonly int _lineWidth; + private readonly int _bigFontLineWidth; + + public OrderItemsReceiptConverter(int lineWidth, int bigFontLineWidth) + { + _lineWidth = lineWidth; + _bigFontLineWidth = bigFontLineWidth; + } + + public List Convert(string jsonContent) + { + var receipt = JsonSerializer.Deserialize(jsonContent); + var converter = new ReceiptConverter(_lineWidth, _bigFontLineWidth); + return converter.ConvertToPrintCommands(receipt); + } +} diff --git a/Inspectron.Epson/PrintServer/Printers/Utils/OrderItems/ReceiptConverter.cs b/Inspectron.Epson/PrintServer/Printers/Utils/OrderItems/ReceiptConverter.cs index 12ab320..2cfed36 100644 --- a/Inspectron.Epson/PrintServer/Printers/Utils/OrderItems/ReceiptConverter.cs +++ b/Inspectron.Epson/PrintServer/Printers/Utils/OrderItems/ReceiptConverter.cs @@ -159,10 +159,10 @@ public class ReceiptConverter } } - // Comment + // SpecialInstruction if (!string.IsNullOrEmpty(item.Comment)) { - commands.Add(new PrintCommand($" Comment: {item.Comment}")); + commands.Add(new PrintCommand($" SpecialInstruction: {item.Comment}")); } } diff --git a/Inspectron.Epson/PrintServer/Printers/Utils/ReceiptConverterFactory.cs b/Inspectron.Epson/PrintServer/Printers/Utils/ReceiptConverterFactory.cs new file mode 100644 index 0000000..5ce970c --- /dev/null +++ b/Inspectron.Epson/PrintServer/Printers/Utils/ReceiptConverterFactory.cs @@ -0,0 +1,25 @@ +using Inspectron.Epson.PrintServer.Printers.Utils.OrderItems; + +namespace Inspectron.Epson.PrintServer.Printers.Utils; + +public class ReceiptConverterFactory : IReceiptConverterFactory +{ + public IReceiptConverter Create(int receiptType, int lineWidth, int bigFontLineWidth) + { + return (EReceiptType)receiptType switch + { + EReceiptType.Receipt => new FinalReceipt.FinalReceiptConverter(lineWidth, bigFontLineWidth), + EReceiptType.WorkareaTicket => new KitchenReceipt.KitchenReceiptConverterAdapter(33, 20), + EReceiptType.NextCourse => new KitchenReceipt.KitchenReceiptConverterAdapter(33, 20), + EReceiptType.OrdersOverview => new OrderItemsReceiptConverter(lineWidth, bigFontLineWidth), + _ => throw new ArgumentException($"Unknown receipt type: {receiptType}") + }; + } + public enum EReceiptType + { + Receipt, + WorkareaTicket, + NextCourse, + OrdersOverview + } +} diff --git a/Inspectron.Epson/PrintServer/Printers/Utils/ReceiptTranslator.cs b/Inspectron.Epson/PrintServer/Printers/Utils/ReceiptTranslator.cs deleted file mode 100644 index 15ddc50..0000000 --- a/Inspectron.Epson/PrintServer/Printers/Utils/ReceiptTranslator.cs +++ /dev/null @@ -1,206 +0,0 @@ -namespace Inspectron.Epson.PrintServer.Printers.Utils; - - -public record TranslatedKitchenReceipt(string Location, string Date, string Owner, string Tisch, List items) :ASTNode; -public record KitchenItem(string Name) : ASTNode; -public record KitchenProduct(int Amount, string Name) : KitchenItem(Name); -public record KitchenGang(string Name) : KitchenItem(Name); - -public record FinalReceipt(string Location, string Phone, string URL, string Date, List items, string total, string MWST, string Comment, string Thanks) : ASTNode; -public record FinalReceiptItem(string Name, int Amount, string Price, string Total) : ASTNode; - - -public class ReceiptTranslator -{ - public ASTNode ParseReceipt(string receiptText) - { - // Determine receipt type based on content - bool isFinalReceipt = receiptText.Contains("http") || - receiptText.Contains("+41") || - receiptText.Contains("Summe CHF") || - receiptText.Contains("MWST") || - receiptText.Contains("Thank you"); - - bool isKitchenReceipt = receiptText.Contains("TISCH:"); - - if (isKitchenReceipt && !isFinalReceipt) - { - return ParseKitchenReceipt(receiptText); - } - else if (isFinalReceipt) - { - return ParseFinalReceipt(receiptText); - } - else - { - // Default to kitchen receipt if unclear - return ParseKitchenReceipt(receiptText); - } - } - - public static FinalReceipt ParseFinalReceipt(string receiptText) - { - var lines = receiptText.Split('\n', StringSplitOptions.RemoveEmptyEntries) - .Select(l => l.Trim()) - .ToList(); - - // Extract header information - string location = lines[0]; - string phone = lines[1]; - string url = lines[2]; - - // Find and extract date - var dateLine = lines.FirstOrDefault(l => l.StartsWith("Datum:")); - string date = dateLine?.Replace("Datum:", "").Trim() ?? ""; - - // Find total line - var totalLine = lines.FirstOrDefault(l => l.Contains("Summe CHF :")); - string total = totalLine?.Split(':').Last().Trim() ?? ""; - - // Find MWST line (comes after "TOTAL MWST" header) - var mwstLineIndex = lines.FindIndex(l => l.StartsWith("TOTAL") && l.Contains("MWST")); - string mwst = mwstLineIndex >= 0 && mwstLineIndex + 1 < lines.Count - ? lines[mwstLineIndex + 1].Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).LastOrDefault() ?? "" - : ""; - - // Extract comment (line after MWST values) - string comment = mwstLineIndex >= 0 && mwstLineIndex + 2 < lines.Count - ? lines[mwstLineIndex + 2] - : ""; - - // Extract thank you message (last non-separator line) - string thanks = lines.LastOrDefault(l => !l.Contains("--")) ?? ""; - - // Parse items - var items = new List(); - var startIndex = lines.FindIndex(l => l.StartsWith("Datum:")) + 2; // Skip date and separator - var endIndex = lines.FindIndex(l => l.Contains("Summe CHF")); - - for (int i = startIndex; i < endIndex; i++) - { - var line = lines[i]; - - // Skip separator lines and empty lines - if (line.Contains("---") || string.IsNullOrWhiteSpace(line)) - continue; - - // Check if line contains item data (has * separator) - if (line.Contains("*")) - { - // Parse format: "Name Amount * Price Total" - var parts = line.Split('*'); - if (parts.Length == 2) - { - var leftPart = parts[0].Trim(); - var rightPart = parts[1].Trim(); - - // Extract name and amount from left part - var leftTokens = leftPart.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); - var amount = int.Parse(leftTokens.Last()); - var name = string.Join(" ", leftTokens.Take(leftTokens.Length - 1)); - - // Extract price and total from right part - var rightTokens = rightPart.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); - var price = rightTokens.Length > 0 ? rightTokens[0] : ""; - var itemTotal = rightTokens.Length > 1 ? rightTokens[1] : ""; - - items.Add(new FinalReceiptItem(name, amount, price, itemTotal)); - } - } - } - - return new FinalReceipt(location, phone, url, date, items, total, mwst, comment, thanks); - } - - public static TranslatedKitchenReceipt ParseKitchenReceipt(string receiptText) - { - var lines = receiptText.Split('\n', StringSplitOptions.RemoveEmptyEntries) - .Select(l => l.Trim()) - .ToList(); - - int currentIndex = 0; - - // Skip optional "*** KOPIE ***" header - if (lines[currentIndex].Contains("***")) - { - currentIndex++; - } - - // Extract location (can be any phrase) - string location = lines[currentIndex]; - currentIndex++; - - // Skip separator line - while (currentIndex < lines.Count && lines[currentIndex].Contains("---")) - { - currentIndex++; - } - - // Extract date line - string date = lines[currentIndex]; - currentIndex++; - - // Extract owner - string owner = ""; - do - { - if (owner != "") - { - owner += "/n"; - } - owner += lines[currentIndex]; - currentIndex++; - } while (!lines[currentIndex].ToLower().Contains("tisch:")); - - - // Extract table (extract text after "TISCH:") - string tisch = lines[currentIndex].Replace("TISCH:", "").Trim(); - currentIndex++; - - // Skip empty lines and separators until we reach items - while (currentIndex < lines.Count && - (string.IsNullOrWhiteSpace(lines[currentIndex]) || lines[currentIndex].Contains("-"))) - { - currentIndex++; - } - - // Parse items - var items = new List(); - while (currentIndex < lines.Count) - { - var line = lines[currentIndex]; - - // Stop at separator or end - if (line.Contains("---") || string.IsNullOrWhiteSpace(line)) - { - break; - } - - if (line.ToLower().Contains(". gang")) - { - items.Add(new KitchenGang(line.Trim())); - currentIndex++; - continue; - } - - // Parse format: "1x Espresso" or " 1x Espresso" - var trimmedLine = line.Trim(); - if (trimmedLine.Contains("x")) - { - var parts = trimmedLine.Split('x', 2); - if (parts.Length == 2 && int.TryParse(parts[0].Trim(), out int amount)) - { - var itemName = parts[1].Trim(); - items.Add(new KitchenProduct(amount, itemName)); - } - } - - currentIndex++; - } - - return new TranslatedKitchenReceipt(location, date, owner, tisch, items); - } - - -} -