• 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
Screenshots Loading commit data...
app Loading commit data...
bootstrap Loading commit data...
config Loading commit data...
database Loading commit data...
docker Loading commit data...
docs Loading commit data...
docs-site Loading commit data...
gap-filling-plans Loading commit data...
marketing-site Loading commit data...
plans Loading commit data...
public Loading commit data...
reference/oc-sport Loading commit data...
resources Loading commit data...
routes Loading commit data...
scripts Loading commit data...
storage Loading commit data...
tests Loading commit data...
.dockerignore Loading commit data...
.editorconfig Loading commit data...
.env.example Loading commit data...
.gitattributes Loading commit data...
.gitignore Loading commit data...
.npmrc Loading commit data...
Beanding Guide.txt Loading commit data...
CLAUDE.md Loading commit data...
Dockerfile Loading commit data...
README.md Loading commit data...
artisan Loading commit data...
captain-definition Loading commit data...
composer.json Loading commit data...
composer.lock Loading commit data...
deploy.sh Loading commit data...
elcaptain-sportsonly-db.md Loading commit data...
one-click-app.yml Loading commit data...
package-lock.json Loading commit data...
package.json Loading commit data...
phpunit.xml Loading commit data...
system info.txt Loading commit data...
vite.config.js Loading commit data...
نادى الشيخ زايد كشف بيانات اللاعبين (2).html Loading commit data...