getMessage()); exit(1); } // ── 1) عروض منتهية المهلة ── $expiredSt = $food_con->query( "SELECT id, order_id, courier_id FROM food_courier_assignments WHERE status='offered' AND offered_at < (NOW() - INTERVAL 20 SECOND)" ); foreach ($expiredSt->fetchAll() as $assignment) { $food_con->prepare("UPDATE food_courier_assignments SET status='timed_out', responded_at=NOW() WHERE id=?") ->execute([$assignment['id']]); $orderSt = $food_con->prepare("SELECT merchant_id FROM food_orders WHERE id=? AND status='ready'"); $orderSt->execute([$assignment['order_id']]); $order = $orderSt->fetch(); if (!$order) continue; $merchantSt = $food_con->prepare("SELECT latitude, longitude FROM food_merchants WHERE id=?"); $merchantSt->execute([$order['merchant_id']]); $merchant = $merchantSt->fetch(); if (!$merchant) continue; $candidates = foodFindNearbyCouriers((float)$merchant['latitude'], (float)$merchant['longitude']); $priorSt = $food_con->prepare("SELECT courier_id FROM food_courier_assignments WHERE order_id=?"); $priorSt->execute([$assignment['order_id']]); $prior = array_column($priorSt->fetchAll(), 'courier_id'); foreach ($candidates as $candidateId) { if (in_array($candidateId, $prior, true)) continue; foodOfferOrderToCourier((int)$assignment['order_id'], $candidateId); error_log("[FOOD][CRON] Re-offered order {$assignment['order_id']} to courier {$candidateId} after timeout"); break; } } // ── 2) طلبات pending تجاوزت مهلة رد المطعم ── $stalePendingSt = $food_con->query( "SELECT id, passenger_id, payment_method, grand_total FROM food_orders WHERE status='pending' AND created_at < (NOW() - INTERVAL 5 MINUTE)" ); foreach ($stalePendingSt->fetchAll() as $order) { food_transition_status((int)$order['id'], 'cancelled_system', 'system', 'cron', 'Merchant did not respond within timeout'); if ($order['payment_method'] === 'wallet') { $refunded = foodWalletMove( (string)$order['passenger_id'], (int)$order['grand_total'], 'add', "food-refund-{$order['id']}", "Food order #{$order['id']} auto-cancelled (merchant timeout)" ); $food_con->prepare( "INSERT INTO food_order_payments (order_id, type, amount, status) VALUES (?,'release',?,?)" )->execute([$order['id'], (int)$order['grand_total'], $refunded ? 'success' : 'failed']); if (!$refunded) error_log("[FOOD][CRON] refund FAILED for auto-cancelled order {$order['id']} — needs manual reconciliation"); } } echo "food cron_order_timeouts done\n";