Deploy Ladill POS / deploy (push) Successful in 38s
Guard ingestExternalOrder: skip (200, no ticket created) when the owner has no restaurant-mode POS location, so pushing from Merchant is harmless for accounts that don't use the POS kitchen. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
65 lines
2.2 KiB
PHP
65 lines
2.2 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\Api;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use App\Services\Pos\PosSaleService;
|
|
use Illuminate\Http\JsonResponse;
|
|
use Illuminate\Http\Request;
|
|
use RuntimeException;
|
|
|
|
/**
|
|
* First-party kitchen ingest — lets another Ladill app (e.g. Merchant) push a
|
|
* paid online/QR order onto this account's Kitchen Display. Authenticated with a
|
|
* per-service key (Authorization: Bearer <KITCHEN_API_KEY_*>) and scoped to an
|
|
* account by the `owner` parameter. Idempotent by `reference`.
|
|
*/
|
|
class KitchenIngestController extends Controller
|
|
{
|
|
public function __construct(private PosSaleService $sales) {}
|
|
|
|
public function store(Request $request): JsonResponse
|
|
{
|
|
abort_unless($this->service($request) !== null, 401, 'Invalid service key.');
|
|
|
|
$data = $request->validate([
|
|
'owner' => ['required', 'string', 'max:255'],
|
|
'reference' => ['required', 'string', 'max:255'],
|
|
'customer_name' => ['nullable', 'string', 'max:120'],
|
|
'items' => ['required', 'array', 'min:1', 'max:100'],
|
|
'items.*.name' => ['required', 'string', 'max:200'],
|
|
'items.*.quantity' => ['nullable', 'integer', 'min:1', 'max:200'],
|
|
'items.*.unit_price_minor' => ['nullable', 'integer', 'min:0'],
|
|
'items.*.notes' => ['nullable', 'string', 'max:200'],
|
|
]);
|
|
|
|
try {
|
|
$sale = $this->sales->ingestExternalOrder($data);
|
|
} catch (RuntimeException $e) {
|
|
return response()->json(['message' => $e->getMessage()], 422);
|
|
}
|
|
|
|
// Owner doesn't run a POS kitchen — accept and ignore.
|
|
if ($sale === null) {
|
|
return response()->json(['skipped' => true], 200);
|
|
}
|
|
|
|
return response()->json(['id' => $sale->id, 'reference' => $sale->reference], 201);
|
|
}
|
|
|
|
private function service(Request $request): ?string
|
|
{
|
|
$token = (string) $request->bearerToken();
|
|
if ($token === '') {
|
|
return null;
|
|
}
|
|
foreach ((array) config('pos.kitchen_api_keys', []) as $service => $key) {
|
|
if ((string) $key !== '' && hash_equals((string) $key, $token)) {
|
|
return (string) $service;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
}
|