Update codebase

This commit is contained in:
Hamza-Ayed
2026-08-09 16:56:13 +03:00
parent 95e2e4f35d
commit b64debaa88
1058 changed files with 164327 additions and 113928 deletions
+110
View File
@@ -0,0 +1,110 @@
<?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,
]);