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); } }