• Claude's avatar
    Stamp every transaction with the branch it happened in · cd2faefd
    Claude authored
    Records were reaching the database with no branch, so they belonged to
    no branch and were invisible in every branch view. Three causes:
    
    1. Invoices have no branch_id column, yet three call sites read
       $invoice->branch_id and stored the result. It was always null.
       POSService did this for every point-of-sale payment, which is why the
       walk-in ("عميل عابر") sales had no branch. POS now uses the branch the
       sale was rung up in; the mobile payment controller and InvoiceShow
       take it from the participant being billed.
    
    2. PaymentService::record() only set a branch if its caller happened to
       pass one, and most callers did not.
    
    3. Nothing enforced the rule centrally.
    
    New BelongsToBranch trait stamps the active branch at creation, mirroring
    BelongsToAcademy. It is applied to the models that record an action —
    Payment, Expense, CashSession, FacilityRentPayment, POSTransaction,
    PurchaseOrder, Participant, TrainingGroup — and deliberately not to
    catalogue models such as BasePrice, PricingRule, Product and Employee,
    where a null branch legitimately means "shared across all branches".
    
    The trait adds no global scope on purpose: branch is a reporting lens,
    not an isolation boundary, and scoping globally would break console
    commands, cross-branch reports and the switcher's "all branches" mode.
    It also returns null rather than guessing when there is no request
    context, so scheduled jobs do not misfile academy-wide records.
    
    Also adds a migration trimming stray whitespace — including the
    non-breaking space U+00A0 that survives copy-paste — from names shown to
    users. Those characters are invisible in forms but render as a gap in
    page titles and receipts, and break exact-match lookups.
    Co-Authored-By: 's avatarClaude Opus 5 <noreply@anthropic.com>
    cd2faefd
Payment.php 2.75 KB