36557-vm/mlm_logic.php
Flatlogic Bot 08fcb2dae0 0.2
2025-12-01 21:25:15 +00:00

255 lines
9.9 KiB
PHP

<?php
require_once __DIR__ . '/db/config.php';
/**
* Fetches the upline for a given user.
*
* @param int $userId The ID of the user.
* @param int $levels The number of levels to fetch.
* @return array The upline users.
*/
function get_upline($userId, $levels = 10) {
$upline = [];
$currentUser = $userId;
for ($i = 0; $i < $levels; $i++) {
$db = db();
$stmt = $db->prepare("SELECT sponsor_id FROM users WHERE id = :id");
$stmt->execute([':id' => $currentUser]);
$sponsor = $stmt->fetch(PDO::FETCH_ASSOC);
if ($sponsor && $sponsor['sponsor_id']) {
$upline[] = $sponsor['sponsor_id'];
$currentUser = $sponsor['sponsor_id'];
} else {
break;
}
}
return $upline;
}
/**
* Calculates and distributes commissions for a given booking.
*
* @param int $bookingId The ID of the booking.
*/
function calculate_commissions($bookingId) {
$db = db();
$db->beginTransaction();
try {
// 1. Get booking details
$stmt = $db->prepare("SELECT user_id, amount FROM bookings WHERE id = :booking_id AND status = 'approved'");
$stmt->execute([':booking_id' => $bookingId]);
$booking = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$booking) {
throw new Exception("Booking not found or not approved.");
}
$bookingAmount = $booking['amount'];
$bookingUserId = $booking['user_id'];
// 2. Get upline
$upline = get_upline($bookingUserId, 10);
if (empty($upline)) {
// No upline, nothing to do
$db->commit();
return;
}
// 3. Direct Commission (Level 10)
$directCommission = $bookingAmount * 0.10;
$directSponsorId = $upline[0];
// Insert transaction for direct commission
$stmt = $db->prepare(
"INSERT INTO transactions (user_id, amount, type, description, related_booking_id, related_user_id) VALUES (:user_id, :amount, 'commission_direct', :description, :booking_id, :related_user_id)"
);
$stmt->execute([
':user_id' => $directSponsorId,
':amount' => $directCommission,
':description' => 'Direct commission for booking #' . $bookingId,
':booking_id' => $bookingId,
':related_user_id' => $bookingUserId
]);
$directCommissionTransactionId = $db->lastInsertId();
// Schedule passive income for the sponsor
schedule_passive_income($directCommissionTransactionId, $directSponsorId, $directCommission, $db);
// Update sponsor's wallet and income
$stmt = $db->prepare("UPDATE users SET wallet_balance = wallet_balance + :amount, total_direct_income = total_direct_income + :amount WHERE id = :user_id");
$stmt->execute([':amount' => $directCommission, ':user_id' => $directSponsorId]);
// 4. Team Commissions (Levels 9 down to 1)
$previousLevelCommission = $directCommission;
for ($i = 1; $i < count($upline); $i++) {
$teamCommission = $previousLevelCommission * 0.50;
$uplineMemberId = $upline[$i];
// Insert transaction for team commission
$stmt = $db->prepare(
"INSERT INTO transactions (user_id, amount, type, description, related_booking_id, related_user_id) VALUES (:user_id, :amount, 'commission_team', :description, :booking_id, :related_user_id)"
);
$stmt->execute([
':user_id' => $uplineMemberId,
':amount' => $teamCommission,
':description' => 'Team commission (Level ' . (10 - ($i + 1) + 1) . ') for booking #' . $bookingId,
':booking_id' => $bookingId,
':related_user_id' => $bookingUserId
]);
// Update user's wallet and income
$stmt = $db->prepare("UPDATE users SET wallet_balance = wallet_balance + :amount, total_team_income = total_team_income + :amount WHERE id = :user_id");
$stmt->execute([':amount' => $teamCommission, ':user_id' => $uplineMemberId]);
$previousLevelCommission = $teamCommission;
}
// 5. Calculate Leg Match Bonus
calculate_leg_match_bonus($bookingUserId, $db);
$db->commit();
echo "Commissions calculated and distributed successfully for booking #$bookingId.";
} catch (Exception $e) {
$db->rollBack();
error_log("Commission calculation failed for booking #$bookingId: " . $e->getMessage());
// Handle or log the error appropriately
}
}
/**
* Calculates and distributes leg match bonuses.
*/
/**
* Recursively calculates the total booking volume for a given user and their entire downline.
*
* @param int $userId The ID of the user at the top of the leg.
* @param PDO $db The database connection.
* @return float The total volume of the leg.
*/
function get_leg_volume($userId, $db) {
$totalVolume = 0.0;
// Get the user's own contribution
$stmt = $db->prepare("SELECT cumulative_bookings FROM users WHERE id = :user_id");
$stmt->execute([':user_id' => $userId]);
$user = $stmt->fetch(PDO::FETCH_ASSOC);
if ($user) {
$totalVolume += $user['cumulative_bookings'];
}
// Get all directly sponsored users
$stmt = $db->prepare("SELECT id FROM users WHERE sponsor_id = :sponsor_id");
$stmt->execute([':sponsor_id' => $userId]);
$downline = $stmt->fetchAll(PDO::FETCH_ASSOC);
foreach ($downline as $downlineUser) {
$totalVolume += get_leg_volume($downlineUser['id'], $db);
}
return $totalVolume;
}
/**
* Calculates and distributes leg match bonuses.
*
* @param int $bookingUserId The user who made the original booking.
* @param PDO $db The database connection.
*/
function calculate_leg_match_bonus($bookingUserId, $db) {
// A leg match bonus is paid to the SPONSOR of the user who made the booking,
// based on the performance of their OTHER legs.
// The spec is "5% leg-match paid to user for every INR 10,00,000 leg milestone".
// This implies we check the sponsor's legs.
// Get the sponsor of the person who made the booking
$stmt = $db->prepare("SELECT sponsor_id FROM users WHERE id = :id");
$stmt->execute([':id' => $bookingUserId]);
$sponsor = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$sponsor || !$sponsor['sponsor_id']) {
return; // No sponsor, no bonus to calculate
}
$sponsorId = $sponsor['sponsor_id'];
// Get all the direct downlines of the SPONSOR (these are the legs)
$stmt = $db->prepare("SELECT id FROM users WHERE sponsor_id = :sponsor_id");
$stmt->execute([':sponsor_id' => $sponsorId]);
$legs = $stmt->fetchAll(PDO::FETCH_ASSOC);
$milestoneAmount = 1000000.00;
$bonusPercentage = 0.05;
$bonusAmount = $milestoneAmount * $bonusPercentage;
foreach ($legs as $leg) {
$legUserId = $leg['id'];
$legVolume = get_leg_volume($legUserId, $db);
// Find out how many milestones this leg has already been paid for
$stmt = $db->prepare("SELECT COUNT(*) as count FROM leg_milestones WHERE user_id = :user_id AND leg_user_id = :leg_user_id");
$stmt->execute([':user_id' => $sponsorId, ':leg_user_id' => $legUserId]);
$paidMilestonesCount = $stmt->fetch(PDO::FETCH_ASSOC)['count'];
$achievedMilestones = floor($legVolume / $milestoneAmount);
if ($achievedMilestones > $paidMilestonesCount) {
$newMilestones = $achievedMilestones - $paidMilestonesCount;
for ($i = 0; $i < $newMilestones; $i++) {
$currentMilestoneNumber = $paidMilestonesCount + $i + 1;
$currentMilestoneValue = $currentMilestoneNumber * $milestoneAmount;
// 1. Pay the bonus
$stmt = $db->prepare(
"INSERT INTO transactions (user_id, amount, type, description, related_user_id) VALUES (:user_id, :amount, 'leg_match_bonus', :description, :related_user_id)"
);
$stmt->execute([
':user_id' => $sponsorId,
':amount' => $bonusAmount,
':description' => "Leg match bonus for leg of user #$legUserId reaching milestone ₹" . number_format($currentMilestoneValue),
':related_user_id' => $legUserId
]);
// 2. Update wallet
$stmt = $db->prepare("UPDATE users SET wallet_balance = wallet_balance + :amount, total_leg_match_income = total_leg_match_income + :amount WHERE id = :user_id");
$stmt->execute([':amount' => $bonusAmount, ':user_id' => $sponsorId]);
// 3. Record the milestone payment
$stmt = $db->prepare("INSERT INTO leg_milestones (user_id, leg_user_id, milestone_amount, bonus_amount) VALUES (:user_id, :leg_user_id, :milestone_amount, :bonus_amount)");
$stmt->execute([
':user_id' => $sponsorId,
':leg_user_id' => $legUserId,
':milestone_amount' => $currentMilestoneValue,
':bonus_amount' => $bonusAmount
]);
}
}
}
}
/**
* Schedules passive income payments.
*/
function schedule_passive_income($directCommissionTransactionId, $userId, $directCommissionAmount, $db) {
$passiveIncomeAmount = $directCommissionAmount * 0.005;
$startDate = new DateTime();
for ($i = 1; $i <= 12; $i++) {
$paymentDate = clone $startDate;
$paymentDate->add(new DateInterval("P{$i}M"));
$stmt = $db->prepare(
"INSERT INTO passive_income_schedule (transaction_id, user_id, amount, payment_date, status) VALUES (:transaction_id, :user_id, :amount, :payment_date, 'pending')"
);
$stmt->execute([
':transaction_id' => $directCommissionTransactionId,
':user_id' => $userId,
':amount' => $passiveIncomeAmount,
':payment_date' => $paymentDate->format('Y-m-d')
]);
}
}