Push paid menu orders to the Ladill POS kitchen
Deploy Ladill Merchant / deploy (push) Successful in 45s

When a menu (food) storefront order is paid, best-effort POST it to the
merchant's Ladill POS kitchen ingest (config/kitchen.php → KITCHEN_API_URL/KEY)
so it lands on their Kitchen Display alongside dine-in tabs. Failures are logged,
never surfaced — order completion is unaffected; POS ignores orders for accounts
that don't run a POS kitchen.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
isaacclad
2026-06-24 23:57:30 +00:00
co-authored by Claude Opus 4.8
parent 20ec89f534
commit 2ced61fed0
3 changed files with 70 additions and 0 deletions
+59
View File
@@ -0,0 +1,59 @@
<?php
namespace App\Services\Merchant;
use App\Models\QrCode;
use App\Models\QrSaleOrder;
use Illuminate\Support\Facades\Http;
/**
* Pushes a paid menu (food) storefront order to the merchant's Ladill POS
* Kitchen Display. Best-effort: failures are logged, never surfaced they must
* not break order completion. POS ignores orders for accounts not running a POS
* kitchen, so this is safe to call for every menu order.
*/
class KitchenPusher
{
public function push(QrSaleOrder $order): void
{
$url = (string) config('kitchen.url');
$key = (string) config('kitchen.key');
if ($url === '' || $key === '') {
return;
}
$order->loadMissing('qrCode', 'merchant');
// Only food menus feed a kitchen.
if (($order->qrCode?->type) !== QrCode::TYPE_MENU || ! $order->merchant) {
return;
}
$items = collect((array) $order->items)
->filter(fn ($i) => strtolower(trim((string) ($i['name'] ?? ''))) !== 'shipping')
->map(fn ($i) => [
'name' => (string) ($i['name'] ?? ''),
'quantity' => max(1, (int) ($i['qty'] ?? 1)),
'unit_price_minor' => (int) round(((float) ($i['price_ghs'] ?? 0)) * 100),
])
->filter(fn ($i) => $i['name'] !== '')
->values()
->all();
if ($items === []) {
return;
}
try {
Http::withToken($key)->acceptJson()->asJson()->timeout(8)
->post($url.'/kitchen/orders', [
'owner' => (string) $order->merchant->public_id,
'reference' => (string) ($order->payment_reference ?: ('QO-'.$order->id)),
'customer_name' => $order->customer_name,
'items' => $items,
]);
} catch (\Throwable $e) {
report($e);
}
}
}
@@ -20,6 +20,7 @@ class MerchantSaleService
private PaystackService $paystack,
private BillingClient $billing,
private SmsService $sms,
private KitchenPusher $kitchen,
) {}
/**
@@ -217,6 +218,7 @@ class MerchantSaleService
]);
$this->notifyOrderPlaced($order->fresh(['qrCode', 'merchant']));
$this->kitchen->push($order->fresh(['qrCode', 'merchant']));
return $order;
}
@@ -257,6 +259,7 @@ class MerchantSaleService
);
$this->notifyOrderPlaced($order->fresh(['qrCode', 'merchant']));
$this->kitchen->push($order->fresh(['qrCode', 'merchant']));
return $order;
}
+8
View File
@@ -0,0 +1,8 @@
<?php
return [
// Ladill POS kitchen ingest — paid food-storefront orders are pushed here so
// they appear on the merchant's POS Kitchen Display. Empty = disabled.
'url' => rtrim((string) env('KITCHEN_API_URL', ''), '/'),
'key' => env('KITCHEN_API_KEY'),
];