prepare( "SELECT t.id, t.route_id, t.status, r.name_ar AS route_name, r.direction FROM transit_trips t JOIN transit_routes r ON r.id = t.route_id WHERE t.id=? AND t.driver_id=? LIMIT 1" ); $st->execute([$tripId, $driverId]); $trip = $st->fetch(); if (!$trip) jsonError('Trip not found', 404); if ($trip['status'] !== 'started') jsonError('Trip is not in started state', 409); $transit_con->prepare( "UPDATE transit_trips SET status='completed', completed_at=NOW(), updated_at=NOW() WHERE id=?" )->execute([$tripId]); global $redis; if ($redis) $redis->del("transit:trip:{$tripId}:status"); // موقع الباص + ملكية الرحلة على Redis سيرفر الموقع transitClearTripOwner($tripId); global $redisLocation; if ($redisLocation) $redisLocation->del("transit:trip:{$tripId}:pos"); // إشعار أولياء الأمور — وصول (ذهاب) أو عودة (إياب) حسب اتجاه الخط $guardEvent = ($trip['direction'] === 'inbound') ? 'return' : 'arrive'; $guardTitle = ($guardEvent === 'return') ? 'عاد الباص 🏠' : 'وصل الباص 🎓'; $guardBody = ($guardEvent === 'return') ? 'وصل باص خط ' . $trip['route_name'] . ' إلى محطته الأخيرة.' : 'وصل باص خط ' . $trip['route_name'] . ' إلى وجهته.'; $stGuardEnroll = $transit_con->prepare( "SELECT id FROM transit_enrollments WHERE preferred_route_id=? AND status='active'" ); $stGuardEnroll->execute([(int)$trip['route_id']]); foreach ($stGuardEnroll->fetchAll(PDO::FETCH_COLUMN) as $enrollId) { transitNotifyGuardians((int)$enrollId, $guardEvent, $guardTitle, $guardBody); } jsonSuccess(['trip_id' => $tripId, 'status' => 'completed'], 'Trip completed');