Files
ladill-pos/app/Http/Controllers/Api/KitchenIngestController.php
T
isaaccladandClaude Opus 4.8 e9d483394c
Deploy Ladill POS / deploy (push) Successful in 38s
Only ingest online orders for accounts running a POS kitchen
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>
2026-06-24 23:50:52 +00:00

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;
}
}