Initial commit

This commit is contained in:
AJ
2025-10-03 23:43:21 -04:00
commit d579029492
288 changed files with 100048 additions and 0 deletions

View File

@@ -0,0 +1,121 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using MoneyMap.Data;
using MoneyMap.Models;
using MoneyMap.Services;
namespace MoneyMap.Pages
{
public class ViewReceiptModel : PageModel
{
private readonly MoneyMapContext _db;
private readonly IReceiptManager _receiptManager;
private readonly IEnumerable<IReceiptParser> _parsers;
public ViewReceiptModel(
MoneyMapContext db,
IReceiptManager receiptManager,
IEnumerable<IReceiptParser> parsers)
{
_db = db;
_receiptManager = receiptManager;
_parsers = parsers;
}
public Receipt Receipt { get; set; } = null!;
public List<ReceiptLineItem> LineItems { get; set; } = new();
public List<ReceiptParseLog> ParseLogs { get; set; } = new();
public List<ParserOption> AvailableParsers { get; set; } = new();
public string ReceiptUrl { get; set; } = "";
[TempData]
public string? SuccessMessage { get; set; }
[TempData]
public string? ErrorMessage { get; set; }
public async Task<IActionResult> OnGetAsync(long id)
{
Receipt = await _db.Receipts
.Include(r => r.Transaction)
.Include(r => r.LineItems)
.Include(r => r.ParseLogs.OrderByDescending(pl => pl.StartedAtUtc))
.FirstOrDefaultAsync(r => r.Id == id);
if (Receipt == null)
return NotFound();
LineItems = Receipt.LineItems?.OrderBy(li => li.LineNumber).ToList() ?? new();
ParseLogs = Receipt.ParseLogs?.OrderByDescending(pl => pl.StartedAtUtc).ToList() ?? new();
// Get receipt URL for display - use handler parameter
ReceiptUrl = $"/ViewReceipt/{id}?handler=file";
// Get available parsers
AvailableParsers = _parsers.Select(p => new ParserOption
{
Name = p.GetType().Name.Replace("ReceiptParser", ""),
FullName = p.GetType().Name
}).ToList();
return Page();
}
public async Task<IActionResult> OnGetFileAsync(long id)
{
var receipt = await _receiptManager.GetReceiptAsync(id);
if (receipt == null)
return NotFound();
var filePath = _receiptManager.GetReceiptPhysicalPath(receipt);
if (!System.IO.File.Exists(filePath))
return NotFound("Receipt file not found on disk.");
var fileBytes = await System.IO.File.ReadAllBytesAsync(filePath);
// For PDFs, set content disposition to inline so they display in browser
if (receipt.ContentType == "application/pdf")
{
Response.Headers.Append("Content-Disposition", $"inline; filename=\"{receipt.FileName}\"");
return File(fileBytes, "application/pdf");
}
return File(fileBytes, receipt.ContentType);
}
public async Task<IActionResult> OnPostParseAsync(long id, string parser)
{
var selectedParser = _parsers.FirstOrDefault(p => p.GetType().Name == parser);
if (selectedParser == null)
{
ErrorMessage = "Parser not found.";
return RedirectToPage(new { id });
}
var result = await selectedParser.ParseReceiptAsync(id);
if (result.IsSuccess)
{
SuccessMessage = result.Message;
}
else
{
ErrorMessage = result.Message;
}
return RedirectToPage(new { id });
}
public class ParserOption
{
public string Name { get; set; } = "";
public string FullName { get; set; } = "";
}
}
}