• Mahmoud Aglan's avatar
    feat(expenses): let one expense carry many receipt images · b3c232ab
    Mahmoud Aglan authored
    An expense is one payment, not one piece of paper. A month of fuel, or a kit
    order settled across a dozen shops, arrives at the desk as a single expense
    with a hundred receipts behind it. The schema had one set of `attachment_*`
    columns on `expenses`, which encoded the opposite assumption, and
    attachReceipt() deleted the file it displaced — so uploading page two of an
    invoice destroyed page one and nothing said so.
    
    Receipts move to their own `expense_attachments` table. The migration is
    additive and idempotent (guarded by hasTable, backfill deduped by path, so it
    is safe against the migrate-on-every-boot entrypoint), and it copies the
    existing single attachments across, defaulting the pre-metadata rows to the
    `public` disk exactly as attachmentDiskName() did in PHP. The old columns are
    deliberately left in place rather than dropped: a client DB is migrated in
    place on a live container and a dropped column is not recoverable.
    
    The desk can now select several files at once and keep adding in batches —
    selections accumulate instead of replacing, which is what a hundred-receipt
    expense actually needs. Deleting one receipt leaves the others alone, and the
    delete re-resolves the id through the expense's own relation so an id off the
    wire cannot erase another expense's evidence. Streaming moves to the
    attachment's own uuid route, with the branch check read from the parent
    expense without global scopes so the guard cannot fail open.
    Co-Authored-By: 's avatarClaude Opus 5 (1M context) <noreply@anthropic.com>
    b3c232ab
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...
flutter_shell Loading commit data...
gap-filling-plans Loading commit data...
lang 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...