• 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
..
Activities Loading commit data...
Admin Loading commit data...
Assignments Loading commit data...
Attendance Loading commit data...
Audit Loading commit data...
Auth Loading commit data...
Branches Loading commit data...
CashSessions Loading commit data...
Components Loading commit data...
Concerns Loading commit data...
Dashboard Loading commit data...
Documents Loading commit data...
Enrollments Loading commit data...
Evaluations Loading commit data...
Events Loading commit data...
Facilities Loading commit data...
Financial Loading commit data...
Groups Loading commit data...
Guardian Loading commit data...
HR Loading commit data...
Inventory Loading commit data...
Invoices Loading commit data...
Messaging Loading commit data...
Notifications Loading commit data...
POS Loading commit data...
Parent Loading commit data...
Participants Loading commit data...
People Loading commit data...
Portal Loading commit data...
Pricing Loading commit data...
Profile Loading commit data...
Programs Loading commit data...
Public Loading commit data...
Receptionist Loading commit data...
Reports Loading commit data...
Requests Loading commit data...
Roles Loading commit data...
Schedule Loading commit data...
Settings Loading commit data...
Trainer Loading commit data...
Training Loading commit data...
Users Loading commit data...
Wallets Loading commit data...
Website Loading commit data...
WhatsApp Loading commit data...
Wizards Loading commit data...
BranchSwitcher.php Loading commit data...
Dashboard.php Loading commit data...
GlobalSearch.php Loading commit data...