Deploy Ladill POS / deploy (push) Successful in 2m15s
Enforce plan location caps in SubscriptionService, surface upgrade copy on plans and branch settings, and cover the limits in tests.
201 lines
6.7 KiB
PHP
201 lines
6.7 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\Pos;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use App\Http\Controllers\Pos\Concerns\ScopesToAccount;
|
|
use App\Models\PosLocation;
|
|
use App\Models\PosSale;
|
|
use App\Models\PosTable;
|
|
use App\Services\Pos\PosLocationService;
|
|
use App\Services\Pos\SubscriptionService;
|
|
use Illuminate\Http\RedirectResponse;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Validation\Rule;
|
|
use Illuminate\View\View;
|
|
|
|
class LocationController extends Controller
|
|
{
|
|
use ScopesToAccount;
|
|
|
|
public function __construct(
|
|
private PosLocationService $locations,
|
|
private SubscriptionService $subscriptions,
|
|
) {}
|
|
|
|
public function index(Request $request): RedirectResponse
|
|
{
|
|
$owner = $this->ownerRef($request);
|
|
|
|
abort_unless(
|
|
app(\App\Services\Pos\PosMemberResolver::class)->canManageBranches(
|
|
$this->posMember($request),
|
|
$owner,
|
|
$this->actor($request),
|
|
),
|
|
403,
|
|
);
|
|
|
|
return redirect()->route('pos.settings')->withFragment('branches');
|
|
}
|
|
|
|
public function create(Request $request): View|RedirectResponse
|
|
{
|
|
return $this->guardManage($request) ?? view('pos.branches.create');
|
|
}
|
|
|
|
public function store(Request $request): RedirectResponse
|
|
{
|
|
if ($redirect = $this->guardManage($request)) {
|
|
return $redirect;
|
|
}
|
|
|
|
$owner = $this->ownerRef($request);
|
|
$account = ladill_account() ?? $request->user();
|
|
|
|
if (! $this->subscriptions->canAddLocation($account, $owner)) {
|
|
return redirect()->route('pos.pro.index')
|
|
->with('upsell', $this->subscriptions->locationLimitMessage($account));
|
|
}
|
|
|
|
$data = $request->validate([
|
|
'name' => ['required', 'string', 'max:120'],
|
|
'currency' => ['required', 'string', 'size:3'],
|
|
'service_style' => ['required', 'in:retail,restaurant'],
|
|
]);
|
|
|
|
if ($data['service_style'] === 'restaurant' && ! $this->subscriptions->canUseRestaurantMode($account)) {
|
|
return back()->withInput()->with('upsell', 'Restaurant mode is part of Ladill POS Pro.');
|
|
}
|
|
|
|
$isFirst = $this->subscriptions->locationCount($owner) === 0;
|
|
|
|
PosLocation::create([
|
|
'owner_ref' => $owner,
|
|
'name' => $data['name'],
|
|
'currency' => strtoupper($data['currency']),
|
|
'service_style' => $data['service_style'],
|
|
'is_default' => $isFirst,
|
|
]);
|
|
|
|
return redirect()->route('pos.settings')->withFragment('branches')->with('success', 'Branch created.');
|
|
}
|
|
|
|
public function edit(Request $request, PosLocation $location): View|RedirectResponse
|
|
{
|
|
$this->authorizeOwner($request, $location);
|
|
if ($redirect = $this->guardManage($request)) {
|
|
return $redirect;
|
|
}
|
|
|
|
return view('pos.branches.edit', compact('location'));
|
|
}
|
|
|
|
public function update(Request $request, PosLocation $location): RedirectResponse
|
|
{
|
|
$this->authorizeOwner($request, $location);
|
|
if ($redirect = $this->guardManage($request)) {
|
|
return $redirect;
|
|
}
|
|
|
|
$account = ladill_account() ?? $request->user();
|
|
$data = $request->validate([
|
|
'name' => ['required', 'string', 'max:120'],
|
|
'currency' => ['required', 'string', 'size:3'],
|
|
'service_style' => ['required', 'in:retail,restaurant'],
|
|
'is_default' => ['sometimes', 'boolean'],
|
|
]);
|
|
|
|
if ($data['service_style'] === 'restaurant' && ! $this->subscriptions->canUseRestaurantMode($account)) {
|
|
return back()->withInput()->with('upsell', 'Restaurant mode is part of Ladill POS Pro.');
|
|
}
|
|
|
|
if ($request->boolean('is_default')) {
|
|
PosLocation::owned($this->ownerRef($request))
|
|
->where('id', '!=', $location->id)
|
|
->update(['is_default' => false]);
|
|
$location->is_default = true;
|
|
}
|
|
|
|
$location->update([
|
|
'name' => $data['name'],
|
|
'currency' => strtoupper($data['currency']),
|
|
'service_style' => $data['service_style'],
|
|
]);
|
|
|
|
return redirect()->route('pos.settings')->withFragment('branches')->with('success', 'Branch updated.');
|
|
}
|
|
|
|
public function destroy(Request $request, PosLocation $location): RedirectResponse
|
|
{
|
|
$this->authorizeOwner($request, $location);
|
|
if ($redirect = $this->guardManage($request)) {
|
|
return $redirect;
|
|
}
|
|
|
|
$owner = $this->ownerRef($request);
|
|
|
|
if (PosLocation::owned($owner)->count() <= 1) {
|
|
return back()->with('error', 'You must keep at least one branch.');
|
|
}
|
|
|
|
if (PosSale::owned($owner)->where('location_id', $location->id)->exists()) {
|
|
return back()->with('error', 'This branch has sales history and cannot be removed.');
|
|
}
|
|
|
|
if (PosTable::owned($owner)->where('location_id', $location->id)->where('status', '!=', PosTable::STATUS_FREE)->exists()) {
|
|
return back()->with('error', 'Settle open tickets on this branch before removing it.');
|
|
}
|
|
|
|
$wasDefault = $location->is_default;
|
|
$location->delete();
|
|
|
|
if ($wasDefault) {
|
|
PosLocation::owned($owner)->orderBy('id')->first()?->update(['is_default' => true]);
|
|
}
|
|
|
|
if ((int) $request->session()->get('ladill_pos_location') === (int) $location->id) {
|
|
$request->session()->forget('ladill_pos_location');
|
|
}
|
|
|
|
return redirect()->route('pos.settings')->withFragment('branches')->with('success', 'Branch removed.');
|
|
}
|
|
|
|
public function switch(Request $request): RedirectResponse
|
|
{
|
|
$owner = $this->ownerRef($request);
|
|
$data = $request->validate([
|
|
'location' => [
|
|
'required',
|
|
'integer',
|
|
Rule::exists('pos_locations', 'id')->where('owner_ref', $owner),
|
|
],
|
|
]);
|
|
|
|
$this->locations->switch($request, (int) $data['location']);
|
|
|
|
return back()->with('success', 'Switched branch.');
|
|
}
|
|
|
|
private function guardManage(Request $request): ?RedirectResponse
|
|
{
|
|
$owner = $this->ownerRef($request);
|
|
|
|
if (! app(\App\Services\Pos\PosMemberResolver::class)->canManageBranches(
|
|
$this->posMember($request),
|
|
$owner,
|
|
$this->actor($request),
|
|
)) {
|
|
abort(403);
|
|
}
|
|
|
|
$account = ladill_account() ?? $request->user();
|
|
if (! $this->subscriptions->canUseMultiLocation($account)) {
|
|
return redirect()->route('pos.pro.index')
|
|
->with('upsell', 'Multi-branch POS requires Ladill POS Pro or Business.');
|
|
}
|
|
|
|
return null;
|
|
}
|
|
}
|