Add multi-branch POS with team roles and branch-scoped cashiers.
Deploy Ladill POS / deploy (push) Successful in 1m58s

Pro and Business users can manage branches, invite cashiers with branch assignment, and switch registers; sales and register flows respect acting location.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
isaacclad
2026-07-08 06:05:30 +00:00
co-authored by Cursor
parent cac7c60415
commit 9d7dac6c24
34 changed files with 1434 additions and 30 deletions
@@ -2,6 +2,11 @@
namespace App\Http\Controllers\Pos\Concerns;
use App\Models\PosLocation;
use App\Models\PosMember;
use App\Models\User;
use App\Services\Pos\PosMemberResolver;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Http\Request;
@@ -14,8 +19,63 @@ trait ScopesToAccount
return (string) $user->public_id;
}
protected function actor(Request $request): User
{
return $request->user();
}
protected function posMember(Request $request): ?PosMember
{
return $request->attributes->get('pos.member')
?? app(PosMemberResolver::class)->memberFor($this->actor($request), $this->ownerRef($request));
}
protected function locationScope(Request $request): ?int
{
return $request->attributes->get('pos.locationScope')
?? app(PosMemberResolver::class)->locationScope(
$this->posMember($request),
$this->ownerRef($request),
$this->actor($request),
);
}
protected function location(Request $request): PosLocation
{
$acting = $request->attributes->get('actingLocation');
if ($acting instanceof PosLocation) {
return $acting;
}
return app(\App\Services\Pos\PosLocationService::class)->resolve($request);
}
protected function authorizeOwner(Request $request, Model $model): void
{
abort_unless($model->getAttribute('owner_ref') === $this->ownerRef($request), 404);
$this->authorizeLocation($request, $model);
}
protected function authorizeLocation(Request $request, Model $model): void
{
$scope = $this->locationScope($request);
if ($scope === null) {
return;
}
$locationId = $model->getAttribute('location_id');
if ($locationId !== null) {
abort_unless((int) $locationId === $scope, 404);
}
}
protected function scopeToLocation(Request $request, Builder $query, string $column = 'location_id'): Builder
{
$scope = $this->locationScope($request);
if ($scope !== null) {
$query->where($column, $scope);
}
return $query;
}
}