Update: 2026-07-09 01:55:25

This commit is contained in:
Hamza-Ayed
2026-07-09 01:55:25 +03:00
parent ac0c343f18
commit 7dff7b6973
12 changed files with 374 additions and 28 deletions
+50
View File
@@ -116,4 +116,54 @@ function getCurrencyByCountry(string $countryCode): string {
return $currencies[$countryCode] ?? 'SYP'; // افتراضي: ليرة سورية
}
/**
* يقدّر مقدار زيادة أجرة السائق عندنا مقارنة بأقرب منافس لنفس الرحلة.
* يعتمد على معاملات المنافس المخزّنة بـ Redis (يحدّثها cron_ai_engine.php
* كل 3 ساعات على مفتاح pricing:driver_comparison:{country_code}) — لا يوجد
* أي استعلام مباشر لقاعدة البيانات هنا لتفادي أي تأخير وقت إنشاء الرحلة.
*
* @return array|null ['extra' => float, 'currency' => string, 'competitor_name' => string]
* أو null إذا ما في بيانات كافية أو الفرق مش مجدي يُعرض
*/
function estimateDriverEarningsAdvantage(
string $countryCode,
float $distanceKm,
float $durationMin,
float $ourDriverPrice,
$redis
): ?array {
if (!$redis || $ourDriverPrice <= 0) return null;
try {
$json = $redis->get("pricing:driver_comparison:{$countryCode}");
} catch (Exception $e) {
return null;
}
if (!$json) return null;
$data = json_decode($json, true);
if (!is_array($data) || empty($data['competitor_name'])) return null;
$competitorFare = (float)($data['base_fare'] ?? 0)
+ (float)($data['km_rate'] ?? 0) * $distanceKm
+ (float)($data['min_rate'] ?? 0) * $durationMin;
if ($competitorFare <= 0) return null;
$commissionPct = (float)($data['commission_pct'] ?? 20.0);
$competitorDriverPayout = $competitorFare * (1 - $commissionPct / 100);
$extra = round($ourDriverPrice - $competitorDriverPayout, 2);
// حد أدنى نسبي (3% من أجرة سائق المنافس) حتى ما نعرض فرق تافه أو غير موثوق
$minMeaningful = $competitorDriverPayout * 0.03;
if ($extra <= $minMeaningful) return null;
return [
'extra' => $extra,
'currency' => $data['currency'] ?? 'SYP',
'competitor_name' => $data['competitor_name'],
];
}
?>
+47 -13
View File
@@ -16,23 +16,23 @@ try {
// =================================================================================
// 🛠️ دالة مساعدة: إرسال الرحلة لسوق السائقين (Marketplace Broadcast)
// =================================================================================
function broadcastRideToMarket($rideId, $lat, $lng, $payloadData) {
$url = getenv('LOCATION_SOCKET_URL');
function broadcastRideToMarket($rideId, $lat, $lng, $payloadData, $extraMarketData = []) {
$url = getenv('LOCATION_SOCKET_URL');
$INTERNAL_KEY = function_exists('getInternalSocketKey') ? getInternalSocketKey() : '';
$marketPayload = [
$marketPayload = array_merge([
'id' => (string)$rideId,
'start_lat' => $lat,
'start_lng' => $lng,
'end_lat' => $payloadData[3],
'end_lng' => $payloadData[4],
'price' => $payloadData[2],
'carType' => $payloadData[31],
'startName' => $payloadData[29],
'endName' => $payloadData[30],
'distance' => $payloadData[11],
'duration' => $payloadData[15],
'passengerRate' => $payloadData[33],
];
'price' => $payloadData[2],
'carType' => $payloadData[31],
'startName' => $payloadData[29],
'endName' => $payloadData[30],
'distance' => $payloadData[11],
'duration' => $payloadData[15],
'passengerRate' => $payloadData[33],
], $extraMarketData);
$postData = [
'action' => 'market_new_ride',
@@ -254,6 +254,36 @@ try {
// ═══════════════════════════════════════════════════════════
$kazan = (float) $price - (float) $price_for_driver;
$passengerFp = isset($_SERVER['HTTP_X_DEVICE_FP']) ? $_SERVER['HTTP_X_DEVICE_FP'] : '';
// ── 🆕 "أرباحك أعلى" — مقارنة أجرة السائق عندنا مع أقرب منافس ─────
require_once __DIR__ . '/../pricing/pricing_helper.php';
$extraDispatchData = [];
try {
$rideCountryCode = 'JO';
$stmtCountry = $con->prepare("
SELECT country_code FROM passenger_opening_locations
WHERE passenger_id = :pid
ORDER BY created_at DESC LIMIT 1
");
$stmtCountry->execute([':pid' => $passenger_id]);
$foundCountry = $stmtCountry->fetchColumn();
if ($foundCountry) $rideCountryCode = strtoupper($foundCountry);
$durationMinForEarnings = is_numeric($duration_text) ? (float)$duration_text : 0.0;
$earnings = estimateDriverEarningsAdvantage(
$rideCountryCode,
(float)$distance,
$durationMinForEarnings,
(float)$price_for_driver,
$redis ?? null
);
if ($earnings) {
$extraDispatchData['driver_earnings_extra'] = (string)$earnings['extra'];
$extraDispatchData['driver_earnings_currency'] = $earnings['currency'];
}
} catch (Exception $e) {
error_log("[add_ride] Driver earnings estimate failed: " . $e->getMessage());
}
$payload = [
(string) $startLat,
(string) $startLng,
@@ -290,6 +320,10 @@ try {
number_format($kazan, 2, '.', ''),
(string) $passenger_rating,
(string) $is_prime, // 👑 Index 34: Prime Status
// 🆕 Index 35/36: "أرباحك أعلى" — تُقرأ من نافذة الـ Overlay (order_over_lay.dart)
// اللي بتوصلها البيانات كـ List مش كـ Map مسمّى مثل FCM
isset($extraDispatchData['driver_earnings_extra']) ? $extraDispatchData['driver_earnings_extra'] : '',
isset($extraDispatchData['driver_earnings_currency']) ? $extraDispatchData['driver_earnings_currency'] : '',
];
// Direct dispatch للسائقين القريبين
@@ -369,14 +403,14 @@ try {
}
if (!empty($driversData)) {
dispatchRideToDrivers($driversData, $insertedId, $payload, $start_name_loc, $encryptionHelper);
dispatchRideToDrivers($driversData, $insertedId, $payload, $start_name_loc, $encryptionHelper, $extraDispatchData);
error_log("[add_ride] Dispatched RideID=$insertedId to " . count($driversData) . " drivers.");
} else {
error_log("[add_ride] No direct drivers found for RideID=$insertedId — market only.");
}
// Broadcast للـ marketplace دائماً
broadcastRideToMarket($insertedId, $startLat, $startLng, $payload);
broadcastRideToMarket($insertedId, $startLat, $startLng, $payload, $extraDispatchData);
// رد النجاح للتطبيق
printSuccess($insertedId);