111 lines
4.2 KiB
PHP
111 lines
4.2 KiB
PHP
<?php
|
|
// food/cart/quote.php — يحسب السعر من الخادم فقط ويوقّعه لمدة 10 دقائق
|
|
// body: merchant_id, items:[{item_id, quantity, options:[{option_group_id, choice_ids:[]}]}]
|
|
require_once __DIR__ . '/../connect_app.php';
|
|
|
|
$merchantId = filterRequest('merchant_id', 'int');
|
|
$itemsRaw = json_decode(filterRequest('items') ?? '[]', true);
|
|
if (!$merchantId || !$itemsRaw || !is_array($itemsRaw)) {
|
|
jsonError('merchant_id and items are required');
|
|
}
|
|
|
|
$merchantSt = $food_con->prepare(
|
|
"SELECT id, min_order_amount, is_open_override, working_hours FROM food_merchants WHERE id=? AND status='active' LIMIT 1"
|
|
);
|
|
$merchantSt->execute([$merchantId]);
|
|
$merchant = $merchantSt->fetch();
|
|
if (!$merchant) jsonError('Merchant not found', 404);
|
|
if (!foodIsMerchantOpen($merchant)) jsonError('Merchant is currently closed', 409);
|
|
|
|
$lines = [];
|
|
$itemsTotal = 0;
|
|
|
|
foreach ($itemsRaw as $line) {
|
|
$itemId = (int)($line['item_id'] ?? 0);
|
|
$quantity = max(1, (int)($line['quantity'] ?? 1));
|
|
if (!$itemId) jsonError('Invalid item in cart');
|
|
|
|
$itemSt = $food_con->prepare(
|
|
"SELECT id, merchant_id, name_ar, price, is_available FROM food_menu_items WHERE id=? LIMIT 1"
|
|
);
|
|
$itemSt->execute([$itemId]);
|
|
$item = $itemSt->fetch();
|
|
if (!$item || (int)$item['merchant_id'] !== $merchantId) jsonError("Item $itemId does not belong to this merchant", 400);
|
|
if (!$item['is_available']) jsonError("{$item['name_ar']} is currently unavailable", 409);
|
|
|
|
$optionsSt = $food_con->prepare("SELECT id, choices, is_required, max_select FROM food_item_options WHERE item_id=?");
|
|
$optionsSt->execute([$itemId]);
|
|
$optionGroups = $optionsSt->fetchAll();
|
|
|
|
$chosenOptionsOut = [];
|
|
$optionsTotalPerUnit = 0;
|
|
$requestedGroups = $line['options'] ?? [];
|
|
|
|
foreach ($optionGroups as $group) {
|
|
$choices = json_decode($group['choices'], true) ?: [];
|
|
$choiceById = array_column($choices, null, 'id');
|
|
$requested = null;
|
|
foreach ($requestedGroups as $rg) {
|
|
if ((int)($rg['option_group_id'] ?? 0) === (int)$group['id']) { $requested = $rg; break; }
|
|
}
|
|
$choiceIds = $requested['choice_ids'] ?? [];
|
|
|
|
if ($group['is_required'] && empty($choiceIds)) {
|
|
jsonError("Required option group missing for item {$item['name_ar']}", 400);
|
|
}
|
|
if (count($choiceIds) > (int)$group['max_select']) {
|
|
jsonError("Too many choices selected for item {$item['name_ar']}", 400);
|
|
}
|
|
|
|
foreach ($choiceIds as $cid) {
|
|
if (!isset($choiceById[$cid])) jsonError("Invalid option choice for item {$item['name_ar']}", 400);
|
|
$optionsTotalPerUnit += (int)$choiceById[$cid]['price'];
|
|
$chosenOptionsOut[] = ['group_id' => (int)$group['id'], 'choice_id' => $cid, 'price' => (int)$choiceById[$cid]['price']];
|
|
}
|
|
}
|
|
|
|
$unitPrice = (int)$item['price'] + $optionsTotalPerUnit;
|
|
$lineTotal = $unitPrice * $quantity;
|
|
$itemsTotal += $lineTotal;
|
|
|
|
$lines[] = [
|
|
'item_id' => $itemId,
|
|
'name_ar_snapshot' => $item['name_ar'],
|
|
'unit_price' => $unitPrice,
|
|
'quantity' => $quantity,
|
|
'options' => $chosenOptionsOut,
|
|
'line_total' => $lineTotal,
|
|
];
|
|
}
|
|
|
|
if ($itemsTotal < (int)$merchant['min_order_amount']) {
|
|
jsonError('Order does not meet minimum order amount', 409, ['min_order_amount' => (int)$merchant['min_order_amount']]);
|
|
}
|
|
|
|
// رسم التوصيل — ثابت من env حتى يُربط بمحرك التسعير القائم في مرحلة لاحقة
|
|
$deliveryFee = (int)(getenv('FOOD_DELIVERY_BASE_FEE') ?: 1000);
|
|
$serviceFee = 0;
|
|
$grandTotal = $itemsTotal + $deliveryFee + $serviceFee;
|
|
|
|
$quote = [
|
|
'merchant_id' => $merchantId,
|
|
'passenger_id' => $food_passenger_id,
|
|
'lines' => $lines,
|
|
'items_total' => $itemsTotal,
|
|
'delivery_fee' => $deliveryFee,
|
|
'service_fee' => $serviceFee,
|
|
'grand_total' => $grandTotal,
|
|
];
|
|
|
|
$token = foodSignQuote($quote);
|
|
|
|
jsonSuccess([
|
|
'quote_token' => $token,
|
|
'items_total' => $itemsTotal,
|
|
'delivery_fee' => $deliveryFee,
|
|
'service_fee' => $serviceFee,
|
|
'grand_total' => $grandTotal,
|
|
'lines' => $lines,
|
|
'expires_in' => 600,
|
|
]);
|