Update: 2026-06-10 02:44:54

This commit is contained in:
Hamza-Ayed
2026-06-10 02:44:55 +03:00
parent 9bc7a31c94
commit a0473a8b0f
134 changed files with 1706 additions and 544 deletions

View File

@@ -0,0 +1,36 @@
-- 1. Table for storing the unified 6-digit referral code for each user (Driver/Passenger)
CREATE TABLE `user_referral_codes` (
`id` INT NOT NULL AUTO_INCREMENT,
`user_id` VARCHAR(100) NOT NULL,
`user_type` ENUM('driver', 'passenger') NOT NULL,
`referral_code` VARCHAR(6) NOT NULL,
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `idx_user_type_id` (`user_id`, `user_type`),
UNIQUE KEY `idx_referral_code` (`referral_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
-- 2. Table for tracking the referral relationship and trip counts
CREATE TABLE `unified_referrals` (
`id` INT NOT NULL AUTO_INCREMENT,
`inviter_code` VARCHAR(6) NOT NULL,
`invited_user_id` VARCHAR(100) NOT NULL,
`invited_user_type` ENUM('driver', 'passenger') NOT NULL,
`status` ENUM('registered', 'active', 'completed') NOT NULL DEFAULT 'registered',
`trip_count` INT NOT NULL DEFAULT 0,
`is_reward_claimed` TINYINT(1) NOT NULL DEFAULT 0,
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `idx_invited_user` (`invited_user_id`, `invited_user_type`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
-- 3. Table for Driver Cash Claims (when a driver requests to receive their reward as manual cash)
CREATE TABLE `driver_cash_claims` (
`id` INT NOT NULL AUTO_INCREMENT,
`driver_id` VARCHAR(100) NOT NULL,
`referral_id` INT NOT NULL,
`amount_syp` INT NOT NULL,
`status` ENUM('pending', 'paid') NOT NULL DEFAULT 'pending',
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

View File

@@ -0,0 +1,37 @@
<?php
require_once __DIR__ . '/../../connect.php';
$inviterCode = filterRequest("inviter_code");
// Use JWT token variables provided by connect.php
if (!$inviterCode || !$user_id || !in_array($role, ['driver', 'passenger'])) {
jsonError("Invalid parameters or unauthorized token");
}
// Ensure the code exists and get the inviter details
$stmtCheck = $con->prepare("SELECT user_id, user_type FROM user_referral_codes WHERE referral_code = ?");
$stmtCheck->execute([$inviterCode]);
if ($stmtCheck->rowCount() == 0) {
jsonError("Invalid referral code");
}
$inviterData = $stmtCheck->fetch(PDO::FETCH_ASSOC);
// Check if user was already invited
$stmtExisting = $con->prepare("SELECT id FROM unified_referrals WHERE invited_user_id = ? AND invited_user_type = ?");
$stmtExisting->execute([$user_id, $role]);
if ($stmtExisting->rowCount() > 0) {
jsonError("User already registered with a referral code");
}
// Insert new referral
$insertStmt = $con->prepare("INSERT INTO unified_referrals (inviter_code, invited_user_id, invited_user_type, status, trip_count, is_reward_claimed) VALUES (?, ?, ?, 'registered', 0, 0)");
try {
$insertStmt->execute([$inviterCode, $user_id, $role]);
printSuccess(["message" => "Referral linked successfully"]);
} catch (PDOException $e) {
jsonError("Database error: " . $e->getMessage());
}
?>

View File

@@ -0,0 +1,80 @@
<?php
require_once __DIR__ . '/../../connect.php';
$referralId = filterRequest("referral_id");
$claimType = filterRequest("claim_type"); // 'wallet' or 'cash'
// Use JWT token variables provided by connect.php
if (!$user_id || $role != 'driver' || !$referralId || !in_array($claimType, ['wallet', 'cash'])) {
jsonError("Invalid parameters or unauthorized token");
}
// 1. Get the referral info
$stmt = $con->prepare("
SELECT r.id, r.inviter_code, r.invited_user_id, r.invited_user_type, r.trip_count, r.is_reward_claimed, c.user_id as inviter_id, c.user_type as inviter_type
FROM unified_referrals r
JOIN user_referral_codes c ON r.inviter_code = c.referral_code
WHERE r.id = ? AND c.user_id = ? AND c.user_type = 'driver'
");
$stmt->execute([$referralId, $user_id]);
if ($stmt->rowCount() == 0) {
jsonError("Referral not found or unauthorized");
}
$referral = $stmt->fetch(PDO::FETCH_ASSOC);
if ($referral['is_reward_claimed'] == 1) {
jsonError("Reward already claimed");
}
// Logic:
// Driver -> Driver: 50 trips = 500 SYP (example)
// Driver -> Passenger: 10 trips = 30 SYP per trip. This could be progressive, but for manual claim we assume completed
$amountSyp = 0;
if ($referral['invited_user_type'] == 'driver') {
if ($referral['trip_count'] >= 50) {
$amountSyp = 500;
} else {
jsonError("Requirement not met (50 trips required)");
}
} else if ($referral['invited_user_type'] == 'passenger') {
if ($referral['trip_count'] >= 1) {
// Here, user gets 30 SYP per trip, max 10. Let's assume claim all at once up to 10.
$tripsToClaim = min($referral['trip_count'], 10);
$amountSyp = $tripsToClaim * 30;
} else {
jsonError("Requirement not met (At least 1 trip required)");
}
}
if ($amountSyp <= 0) {
jsonError("No reward available to claim");
}
try {
$con->beginTransaction();
// Mark as claimed
$updateStmt = $con->prepare("UPDATE unified_referrals SET is_reward_claimed = 1, status = 'claimed' WHERE id = ?");
$updateStmt->execute([$referralId]);
if ($claimType == 'wallet') {
// Add to driver wallet
$walletStmt = $con->prepare("UPDATE driver SET wallet = wallet + ? WHERE id = ?");
$walletStmt->execute([$amountSyp, $user_id]);
} else if ($claimType == 'cash') {
// Request manual cash out
$cashStmt = $con->prepare("INSERT INTO driver_cash_claims (driver_id, referral_id, amount_syp, status) VALUES (?, ?, ?, 'pending')");
$cashStmt->execute([$user_id, $referralId, $amountSyp]);
}
$con->commit();
printSuccess(["message" => "Reward claimed successfully as $claimType"]);
} catch (PDOException $e) {
$con->rollBack();
jsonError("Database error: " . $e->getMessage());
}
?>

View File

@@ -0,0 +1,60 @@
<?php
require_once __DIR__ . '/../../connect.php';
// Use JWT token variables provided by connect.php
if (!$user_id || $role != 'driver') {
jsonError("Invalid parameters or unauthorized token");
}
// 1. Get the driver's referral code
$stmtCode = $con->prepare("SELECT referral_code FROM user_referral_codes WHERE user_id = ? AND user_type = 'driver'");
$stmtCode->execute([$user_id]);
if ($stmtCode->rowCount() == 0) {
// If no code exists, return empty stats
printSuccess([
"referral_code" => null,
"total_invited_drivers" => 0,
"total_invited_passengers" => 0,
"referrals" => []
]);
exit;
}
$referralCode = $stmtCode->fetchColumn();
// 2. Fetch all referrals made by this code
$stmtRefs = $con->prepare("
SELECT id, invited_user_id, invited_user_type, status, trip_count, is_reward_claimed, created_at
FROM unified_referrals
WHERE inviter_code = ?
ORDER BY created_at DESC
");
$stmtRefs->execute([$referralCode]);
$referrals = $stmtRefs->fetchAll(PDO::FETCH_ASSOC);
$totalDrivers = 0;
$totalPassengers = 0;
// Format data and calculate stats
foreach ($referrals as &$ref) {
if ($ref['invited_user_type'] == 'driver') {
$totalDrivers++;
$ref['target_trips'] = 50;
$ref['reward_syp'] = 500;
$ref['can_claim'] = ($ref['trip_count'] >= 50 && $ref['is_reward_claimed'] == 0) ? true : false;
} else {
$totalPassengers++;
$ref['target_trips'] = 1;
$ref['reward_syp'] = 30 * min($ref['trip_count'], 10); // Or max depending on logic
$ref['can_claim'] = ($ref['trip_count'] >= 1 && $ref['is_reward_claimed'] == 0) ? true : false;
}
}
printSuccess([
"referral_code" => $referralCode,
"total_invited_drivers" => $totalDrivers,
"total_invited_passengers" => $totalPassengers,
"referrals" => $referrals
]);
?>

View File

@@ -0,0 +1,60 @@
<?php
require_once __DIR__ . '/../../connect.php';
// Use JWT token variables provided by connect.php
if (!$user_id || $role != 'passenger') {
jsonError("Invalid parameters or unauthorized token");
}
// 1. Get the passenger's referral code
$stmtCode = $con->prepare("SELECT referral_code FROM user_referral_codes WHERE user_id = ? AND user_type = 'passenger'");
$stmtCode->execute([$user_id]);
if ($stmtCode->rowCount() == 0) {
// If no code exists, return empty stats
printSuccess([
"referral_code" => null,
"total_invited_drivers" => 0,
"total_invited_passengers" => 0,
"referrals" => []
]);
exit;
}
$referralCode = $stmtCode->fetchColumn();
// 2. Fetch all referrals made by this code
$stmtRefs = $con->prepare("
SELECT id, invited_user_id, invited_user_type, status, trip_count, is_reward_claimed, created_at
FROM unified_referrals
WHERE inviter_code = ?
ORDER BY created_at DESC
");
$stmtRefs->execute([$referralCode]);
$referrals = $stmtRefs->fetchAll(PDO::FETCH_ASSOC);
$totalDrivers = 0;
$totalPassengers = 0;
// Format data and calculate stats
foreach ($referrals as &$ref) {
if ($ref['invited_user_type'] == 'driver') {
$totalDrivers++;
$ref['target_trips'] = 50;
$ref['reward_syp'] = 500;
$ref['can_claim'] = ($ref['trip_count'] >= 50 && $ref['is_reward_claimed'] == 0) ? true : false;
} else {
$totalPassengers++;
$ref['target_trips'] = 1;
$ref['reward_syp'] = 30; // Just illustrative, rewards are automatic
$ref['can_claim'] = ($ref['trip_count'] >= 1 && $ref['is_reward_claimed'] == 0) ? true : false;
}
}
printSuccess([
"referral_code" => $referralCode,
"total_invited_drivers" => $totalDrivers,
"total_invited_passengers" => $totalPassengers,
"referrals" => $referrals
]);
?>

View File

@@ -0,0 +1,41 @@
<?php
require_once __DIR__ . '/../../connect.php';
function generateUnifiedCode($con) {
while (true) {
$letters = substr(str_shuffle("ABCDEFGHJKLMNPQRSTUVWXYZ"), 0, 2);
$numbers = substr(str_shuffle("23456789"), 0, 4);
$code = $letters . $numbers;
$stmt = $con->prepare("SELECT COUNT(*) FROM user_referral_codes WHERE referral_code = ?");
$stmt->execute([$code]);
if ($stmt->fetchColumn() == 0) {
return $code;
}
}
}
// Ensure the JWT values exist
if (!$user_id || !in_array($role, ['driver', 'passenger'])) {
jsonError("Invalid or missing user information in token");
}
$stmt = $con->prepare("SELECT referral_code FROM user_referral_codes WHERE user_id = ? AND user_type = ?");
$stmt->execute([$user_id, $role]);
if ($stmt->rowCount() > 0) {
$row = $stmt->fetch(PDO::FETCH_ASSOC);
printSuccess(["referral_code" => $row['referral_code']]);
} else {
$newCode = generateUnifiedCode($con);
$insertStmt = $con->prepare("INSERT INTO user_referral_codes (user_id, user_type, referral_code) VALUES (?, ?, ?)");
try {
$insertStmt->execute([$user_id, $role, $newCode]);
printSuccess(["referral_code" => $newCode]);
} catch (PDOException $e) {
jsonError("Database error: " . $e->getMessage());
}
}
?>

View File

@@ -1782,3 +1782,45 @@ CREATE TABLE `write_argument_after_applied_from_background` (
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
-- Dump completed on 2026-04-22 19:40:54
--
-- Table structure for table `user_referral_codes`
--
CREATE TABLE IF NOT EXISTS `user_referral_codes` (
`id` int NOT NULL AUTO_INCREMENT,
`user_id` varchar(100) NOT NULL,
`user_type` enum('driver','passenger') NOT NULL,
`referral_code` varchar(20) NOT NULL UNIQUE,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
--
-- Table structure for table `unified_referrals`
--
CREATE TABLE IF NOT EXISTS `unified_referrals` (
`id` int NOT NULL AUTO_INCREMENT,
`inviter_code` varchar(20) NOT NULL,
`invited_user_id` varchar(100) NOT NULL,
`invited_user_type` enum('driver','passenger') NOT NULL,
`status` enum('registered','first_trip','claimed') DEFAULT 'registered',
`trip_count` int DEFAULT 0,
`is_reward_claimed` tinyint(1) DEFAULT 0,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
--
-- Table structure for table `driver_cash_claims`
--
CREATE TABLE IF NOT EXISTS `driver_cash_claims` (
`id` int NOT NULL AUTO_INCREMENT,
`driver_id` varchar(100) NOT NULL,
`referral_id` int NOT NULL,
`amount_syp` decimal(10,2) NOT NULL,
`status` enum('pending','paid','rejected') DEFAULT 'pending',
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

View File

@@ -208,8 +208,8 @@ CREATE TABLE `car_locations` (
/*!50003 SET @saved_sql_mode = @@sql_mode */ ;
/*!50003 SET sql_mode = 'NO_AUTO_VALUE_ON_ZERO' */ ;
DELIMITER ;;
/*!50003 CREATE*/ /*!50017 DEFINER=`intaleq-rides`@`%`*/ /*!50003 TRIGGER `trg_before_insert_car_locations` BEFORE INSERT ON `car_locations` FOR EACH ROW BEGIN
SET NEW.location_point = ST_PointFromText(CONCAT('POINT(', NEW.longitude, ' ', NEW.latitude, ')'), 4326);
/*!50003 CREATE*/ /*!50017 DEFINER=`intaleq-rides`@`%`*/ /*!50003 TRIGGER `trg_before_insert_car_locations` BEFORE INSERT ON `car_locations` FOR EACH ROW BEGIN
SET NEW.location_point = ST_PointFromText(CONCAT('POINT(', NEW.longitude, ' ', NEW.latitude, ')'), 4326);
END */;;
DELIMITER ;
/*!50003 SET sql_mode = @saved_sql_mode */ ;
@@ -225,10 +225,10 @@ DELIMITER ;
/*!50003 SET @saved_sql_mode = @@sql_mode */ ;
/*!50003 SET sql_mode = 'NO_AUTO_VALUE_ON_ZERO' */ ;
DELIMITER ;;
/*!50003 CREATE*/ /*!50017 DEFINER=`intaleq-rides`@`%`*/ /*!50003 TRIGGER `trg_before_update_car_locations` BEFORE UPDATE ON `car_locations` FOR EACH ROW BEGIN
IF NEW.latitude <> OLD.latitude OR NEW.longitude <> OLD.longitude THEN
SET NEW.location_point = ST_PointFromText(CONCAT('POINT(', NEW.longitude, ' ', NEW.latitude, ')'), 4326);
END IF;
/*!50003 CREATE*/ /*!50017 DEFINER=`intaleq-rides`@`%`*/ /*!50003 TRIGGER `trg_before_update_car_locations` BEFORE UPDATE ON `car_locations` FOR EACH ROW BEGIN
IF NEW.latitude <> OLD.latitude OR NEW.longitude <> OLD.longitude THEN
SET NEW.location_point = ST_PointFromText(CONCAT('POINT(', NEW.longitude, ' ', NEW.latitude, ')'), 4326);
END IF;
END */;;
DELIMITER ;
/*!50003 SET sql_mode = @saved_sql_mode */ ;