207 lines
7.2 KiB
C#
207 lines
7.2 KiB
C#
namespace Inspectron.Epson.PrintServer.Printers.Utils;
|
|
|
|
|
|
public record TranslatedKitchenReceipt(string Location, string Date, string Owner, string Tisch, List<KitchenItem> 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<FinalReceiptItem> 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<FinalReceiptItem>();
|
|
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<KitchenItem>();
|
|
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);
|
|
}
|
|
|
|
|
|
}
|
|
|