Stamp every transaction with the branch it happened in
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:
Claude Opus 5 <noreply@anthropic.com>
Showing
Please register or sign in to comment