diff --git a/MoneyMap/MoneyMap.csproj b/MoneyMap/MoneyMap.csproj
index 1bac5aa..547a48e 100644
--- a/MoneyMap/MoneyMap.csproj
+++ b/MoneyMap/MoneyMap.csproj
@@ -30,4 +30,10 @@
+
+
+ PreserveNewest
+
+
+
diff --git a/MoneyMap/Prompts/ReceiptParserPrompt.txt b/MoneyMap/Prompts/ReceiptParserPrompt.txt
new file mode 100644
index 0000000..784faed
--- /dev/null
+++ b/MoneyMap/Prompts/ReceiptParserPrompt.txt
@@ -0,0 +1,28 @@
+Analyze this receipt image and extract the following information as JSON:
+{
+ "merchant": "store name",
+ "receiptDate": "YYYY-MM-DD" (or null if not found),
+ "dueDate": "YYYY-MM-DD" (or null if not found - for bills only),
+ "subtotal": 0.00 (or null if not found),
+ "tax": 0.00 (or null if not found),
+ "total": 0.00,
+ "confidence": 0.95,
+ "lineItems": [
+ {
+ "description": "item name",
+ "quantity": 1.0 (or null),
+ "unitPrice": 0.00 (or null),
+ "lineTotal": 0.00
+ }
+ ]
+}
+
+Extract all line items you can see on the receipt. For each item:
+- description: The item or service name
+- quantity: Only include if this is an actual countable product (like groceries). For services, fees, charges, or taxes, set to null.
+- unitPrice: Price per unit if quantity applies, otherwise null
+- lineTotal: The total amount for this line (required)
+
+For utility bills, service charges, fees, and taxes - these are NOT products with quantities, so set quantity and unitPrice to null.
+
+If this is a bill (utility, credit card, etc.), look for a due date, payment due date, or deadline and extract it as dueDate. For regular receipts, dueDate should be null.
\ No newline at end of file
diff --git a/MoneyMap/Services/OpenAIReceiptParser.cs b/MoneyMap/Services/OpenAIReceiptParser.cs
index 6b247dc..fb1e715 100644
--- a/MoneyMap/Services/OpenAIReceiptParser.cs
+++ b/MoneyMap/Services/OpenAIReceiptParser.cs
@@ -28,6 +28,7 @@ namespace MoneyMap.Services
private readonly HttpClient _httpClient;
private readonly IMerchantService _merchantService;
private readonly IServiceProvider _serviceProvider;
+ private string? _promptTemplate;
public OpenAIReceiptParser(
MoneyMapContext db,
@@ -205,38 +206,26 @@ namespace MoneyMap.Services
});
}
+ private async Task LoadPromptTemplateAsync()
+ {
+ if (_promptTemplate != null)
+ return _promptTemplate;
+
+ var promptPath = Path.Combine(AppContext.BaseDirectory, "Prompts", "ReceiptParserPrompt.txt");
+
+ if (!File.Exists(promptPath))
+ throw new FileNotFoundException($"Receipt parser prompt template not found at: {promptPath}");
+
+ _promptTemplate = await File.ReadAllTextAsync(promptPath);
+ return _promptTemplate;
+ }
+
private async Task CallOpenAIVisionAsync(string apiKey, string base64Image, string mediaType, string? transactionName = null)
{
- // Build the prompt with optional transaction context
- var promptText = @"Analyze this receipt image and extract the following information as JSON:
-{
- ""merchant"": ""store name"",
- ""receiptDate"": ""YYYY-MM-DD"" (or null if not found),
- ""dueDate"": ""YYYY-MM-DD"" (or null if not found - for bills only),
- ""subtotal"": 0.00 (or null if not found),
- ""tax"": 0.00 (or null if not found),
- ""total"": 0.00,
- ""confidence"": 0.95,
- ""lineItems"": [
- {
- ""description"": ""item name"",
- ""quantity"": 1.0 (or null),
- ""unitPrice"": 0.00 (or null),
- ""lineTotal"": 0.00
- }
- ]
-}
-
-Extract all line items you can see on the receipt. For each item:
-- description: The item or service name
-- quantity: Only include if this is an actual countable product (like groceries). For services, fees, charges, or taxes, set to null.
-- unitPrice: Price per unit if quantity applies, otherwise null
-- lineTotal: The total amount for this line (required)
-
-For utility bills, service charges, fees, and taxes - these are NOT products with quantities, so set quantity and unitPrice to null.
-
-If this is a bill (utility, credit card, etc.), look for a due date, payment due date, or deadline and extract it as dueDate. For regular receipts, dueDate should be null.";
+ // Load the prompt template from file
+ var promptText = await LoadPromptTemplateAsync();
+ // Add transaction context if available
if (!string.IsNullOrWhiteSpace(transactionName))
{
promptText += $"\n\nNote: This transaction was recorded as \"{transactionName}\" in the bank statement, which may help identify the merchant if the receipt is unclear.";