Refactor: Simplify receipt storage path handling
Store only filename in database instead of full relative path. GetReceiptPhysicalPath now combines config base path with filename. AIReceiptParser uses ReceiptManager for consistent path resolution. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -13,10 +13,12 @@ namespace MoneyMap.Services
|
||||
public class AIReceiptParser : IReceiptParser
|
||||
{
|
||||
private readonly MoneyMapContext _db;
|
||||
private readonly IWebHostEnvironment _environment;
|
||||
private readonly IReceiptManager _receiptManager;
|
||||
private readonly IPdfToImageConverter _pdfConverter;
|
||||
private readonly OpenAIVisionClient _openAIClient;
|
||||
private readonly ClaudeVisionClient _claudeClient;
|
||||
private readonly OllamaVisionClient _ollamaClient;
|
||||
private readonly LlamaCppVisionClient _llamaCppClient;
|
||||
private readonly IMerchantService _merchantService;
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
private readonly ILogger<AIReceiptParser> _logger;
|
||||
@@ -24,19 +26,23 @@ namespace MoneyMap.Services
|
||||
|
||||
public AIReceiptParser(
|
||||
MoneyMapContext db,
|
||||
IWebHostEnvironment environment,
|
||||
IReceiptManager receiptManager,
|
||||
IPdfToImageConverter pdfConverter,
|
||||
OpenAIVisionClient openAIClient,
|
||||
ClaudeVisionClient claudeClient,
|
||||
OllamaVisionClient ollamaClient,
|
||||
LlamaCppVisionClient llamaCppClient,
|
||||
IMerchantService merchantService,
|
||||
IServiceProvider serviceProvider,
|
||||
ILogger<AIReceiptParser> logger)
|
||||
{
|
||||
_db = db;
|
||||
_environment = environment;
|
||||
_receiptManager = receiptManager;
|
||||
_pdfConverter = pdfConverter;
|
||||
_openAIClient = openAIClient;
|
||||
_claudeClient = claudeClient;
|
||||
_ollamaClient = ollamaClient;
|
||||
_llamaCppClient = llamaCppClient;
|
||||
_merchantService = merchantService;
|
||||
_serviceProvider = serviceProvider;
|
||||
_logger = logger;
|
||||
@@ -52,10 +58,12 @@ namespace MoneyMap.Services
|
||||
return ReceiptParseResult.Failure("Receipt not found.");
|
||||
|
||||
var selectedModel = model ?? "gpt-4o-mini";
|
||||
var isLlamaCpp = selectedModel.StartsWith("llamacpp:");
|
||||
var isOllama = selectedModel.StartsWith("ollama:");
|
||||
var isClaude = selectedModel.StartsWith("claude-");
|
||||
var provider = isClaude ? "Anthropic" : "OpenAI";
|
||||
var provider = isLlamaCpp ? "LlamaCpp" : (isOllama ? "Ollama" : (isClaude ? "Anthropic" : "OpenAI"));
|
||||
|
||||
var filePath = Path.Combine(_environment.WebRootPath, receipt.StoragePath.Replace("/", Path.DirectorySeparatorChar.ToString()));
|
||||
var filePath = _receiptManager.GetReceiptPhysicalPath(receipt);
|
||||
|
||||
if (!File.Exists(filePath))
|
||||
return ReceiptParseResult.Failure("Receipt file not found on disk.");
|
||||
@@ -96,7 +104,10 @@ namespace MoneyMap.Services
|
||||
promptText += "\n\nRespond ONLY with valid JSON, no other text.";
|
||||
|
||||
// Call appropriate vision API
|
||||
var client = isClaude ? (IAIVisionClient)_claudeClient : _openAIClient;
|
||||
IAIVisionClient client = isLlamaCpp ? _llamaCppClient
|
||||
: isOllama ? _ollamaClient
|
||||
: isClaude ? _claudeClient
|
||||
: _openAIClient;
|
||||
var visionResult = await client.AnalyzeImageAsync(base64Data, mediaType, promptText, selectedModel);
|
||||
|
||||
if (!visionResult.IsSuccess)
|
||||
|
||||
@@ -132,9 +132,8 @@ namespace MoneyMap.Services
|
||||
await file.CopyToAsync(fileStream);
|
||||
}
|
||||
|
||||
// Store relative path in database
|
||||
var relativePath = _configuration["Receipts:StoragePath"] ?? "receipts";
|
||||
var relativeStoragePath = $"{relativePath}/{storedFileName}";
|
||||
// Store just the filename in database (base path comes from config)
|
||||
var relativeStoragePath = storedFileName;
|
||||
|
||||
// Create receipt record
|
||||
var receipt = new Receipt
|
||||
@@ -327,8 +326,8 @@ namespace MoneyMap.Services
|
||||
|
||||
public string GetReceiptPhysicalPath(Receipt receipt)
|
||||
{
|
||||
// StoragePath is like "receipts/filename.jpg"
|
||||
return Path.Combine(_environment.WebRootPath, receipt.StoragePath.Replace("/", Path.DirectorySeparatorChar.ToString()));
|
||||
// StoragePath is just the filename, combine with configured base path
|
||||
return Path.Combine(GetReceiptsBasePath(), receipt.StoragePath);
|
||||
}
|
||||
|
||||
public async Task<Receipt?> GetReceiptAsync(long receiptId)
|
||||
|
||||
Reference in New Issue
Block a user