• Claude's avatar
    Give every expense a receipt you can open · cc417ba9
    Claude authored
    An expense recorded with a scan attached arrived in the database with no
    scan at all. ExpenseForm uploaded the file and passed the path to
    ExpenseService::recordExpense(), which builds its Expense::create() array
    by hand and never copied the two attachment keys across — so the file
    landed on disk and the row forgot about it. It landed on the `public`
    disk too, which needs a storage symlink the containers never create, so
    even a persisted path would have 404'd.
    
    Receipts now go to the private disk and are read back through
    ExpenseAttachmentController, which checks the permission, the academy and
    the active branch before streaming a byte.
    
    The list was also a dead end: a row showed a number and a description and
    offered nothing but "cancel". Rows are now clickable and carry a view
    button, with a paperclip marking the ones that have evidence behind them.
    
    The new detail page is where the expense explains itself — amount,
    category, recipient, method, receipt reference, branch, notes, who
    recorded it and when, and, if it was cancelled, by whom and why. Below
    that sit the journal entries it produced, the original debit/credit pair
    and any reversing entry, so the accounting effect is visible rather than
    implied. The receipt itself previews inline: images as images, PDFs in a
    frame, with download beside them.
    
    An expense recorded without a scan is no longer stuck that way — attach
    one from the detail page, replace it (the displaced file is deleted), or
    remove it. Every attachment records who uploaded it and when. A cancelled
    expense refuses all three: its evidence is frozen with its journal.
    Co-Authored-By: 's avatarClaude Opus 5 <noreply@anthropic.com>
    cc417ba9
Name
Last commit
Last update
..
CertificateController.php Loading commit data...
ContactFormController.php Loading commit data...
Controller.php Loading commit data...
DocumentController.php Loading commit data...
ExpenseAttachmentController.php Loading commit data...
ExportController.php Loading commit data...
GroupSchedulePrintController.php Loading commit data...
HealthController.php Loading commit data...
InvoicePrintController.php Loading commit data...
ParticipantCardController.php Loading commit data...
PublicDocumentController.php Loading commit data...
PublicEventController.php Loading commit data...
PublicWebsiteController.php Loading commit data...
ReceiptController.php Loading commit data...
ReportPrintController.php Loading commit data...
SchedulePrintController.php Loading commit data...
WebsitePageController.php Loading commit data...