Files
exchange-2.0/app/Classes/Modules/Affiliate/Services/TracksAffiliateOrder.php
T
2026-01-27 11:16:58 +08:00

84 lines
2.6 KiB
PHP

<?php
namespace App\Classes\Modules\Affiliate\Services;
use App\Models\Affiliate;
use App\Models\Booking;
use App\Models\User;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
class TracksAffiliateOrder
{
/**
* Track when a user with an affiliate code creates an order
*
* @param Booking $booking
* @return Affiliate|null
*/
public function execute(Booking $booking): ?Affiliate
{
try {
return DB::transaction(function () use ($booking) {
$user = $booking->company->employees()->first();
if (!$user) {
return null;
}
// Get user's affiliate
$userAffiliate = \App\Models\UserAffiliate::where('user_id', $user->id)
->whereNotNull('registered_at')
->first();
if (!$userAffiliate) {
return null;
}
// Lock the affiliate record to prevent race conditions
$affiliate = Affiliate::where('id', $userAffiliate->affiliate_id)
->where('is_active', true)
->lockForUpdate()
->first();
if (!$affiliate) {
return null;
}
// Check if this booking has already been counted
// We'll use a KeyValuePair to track which bookings have been counted
$kvpKey = 'affiliate_order_tracked_' . $affiliate->id;
$existingKvp = $booking->attributesKVP()
->where('key', $kvpKey)
->exists();
if ($existingKvp) {
return $affiliate; // Already counted
}
// Mark this booking as tracked
$keyValuePairObject = new \App\Classes\Modules\KeyValuePairs\DataTransferObjects\KeyValuePairObject(
$kvpKey,
'1'
);
$createsKeyValuePair = app()->make(\App\Classes\Modules\KeyValuePairs\Services\CreatesKeyValuePair::class);
$createsKeyValuePair->execute($booking, $keyValuePairObject);
// Increment orders count atomically
$affiliate->increment('orders_count');
return $affiliate;
});
} catch (\Exception $e) {
Log::error('Failed to track affiliate order', [
'booking_id' => $booking->id,
'error' => $e->getMessage()
]);
return null;
}
}
}