feat: referral_code

This commit is contained in:
2026-06-06 12:21:30 +03:30
parent 20d4336877
commit 0f5f7835e7
4 changed files with 96 additions and 2 deletions
+8
View File
@@ -210,6 +210,7 @@ public function register(Request $request)
'method' => 'string|in:code,link|nullable', 'method' => 'string|in:code,link|nullable',
'birthday' => 'date|nullable', 'birthday' => 'date|nullable',
'gender' => ['integer', 'nullable', Rule::in(User::GENDERS)], 'gender' => ['integer', 'nullable', Rule::in(User::GENDERS)],
'referrer_code' => ['string', 'nullable', 'exists:users,referral_code'],
]); ]);
$method = $data['method'] ?? 'link'; $method = $data['method'] ?? 'link';
@@ -219,6 +220,13 @@ public function register(Request $request)
$packageNameValue = $data['package_name']; $packageNameValue = $data['package_name'];
unset($data['package_name']); unset($data['package_name']);
// Resolve referrer code (کد معرف) to the referring user
$referrerCode = $data['referrer_code'] ?? null;
unset($data['referrer_code']);
if ($referrerCode && $referrer = User::where('referral_code', $referrerCode)->first()) {
$data['referred_by'] = $referrer->id;
}
if (isset($data['mobile'])) { if (isset($data['mobile'])) {
$data['mobile'] = MobileNumberHelper::formatMobile($data['mobile']); $data['mobile'] = MobileNumberHelper::formatMobile($data['mobile']);
if (User::where('mobile', $data['mobile'])->exists()) { if (User::where('mobile', $data['mobile'])->exists()) {
+12 -1
View File
@@ -3,6 +3,7 @@
namespace App\Models; namespace App\Models;
use App\Traits\HasUuid; use App\Traits\HasUuid;
use App\Traits\HasReferralCode;
use DateTimeInterface; use DateTimeInterface;
use EloquentFilter\Filterable; use EloquentFilter\Filterable;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
@@ -13,7 +14,7 @@
use Illuminate\Support\Str; use Illuminate\Support\Str;
class User extends Authenticatable class User extends Authenticatable
{ {
use HasApiTokens, HasFactory, Notifiable, HasUuid, Filterable; use HasApiTokens, HasFactory, Notifiable, HasUuid, HasReferralCode, Filterable;
const GENDERS = [ const GENDERS = [
'male' => 1, 'male' => 1,
@@ -61,6 +62,16 @@ public function otpTokens()
return $this->hasMany(OtpTokens::class); return $this->hasMany(OtpTokens::class);
} }
public function referrer()
{
return $this->belongsTo(User::class, 'referred_by');
}
public function referrals()
{
return $this->hasMany(User::class, 'referred_by');
}
public function transactions() public function transactions()
{ {
return $this->hasMany(Transaction::class); return $this->hasMany(Transaction::class);
+26
View File
@@ -0,0 +1,26 @@
<?php
namespace App\Traits;
use Illuminate\Support\Str;
trait HasReferralCode
{
public static function bootHasReferralCode(): void
{
static::creating(function ($model) {
if (!$model->referral_code) {
$model->referral_code = static::generateReferralCode();
}
});
}
public static function generateReferralCode(): string
{
do {
$code = strtoupper(Str::random(8));
} while (static::where('referral_code', $code)->exists());
return $code;
}
}
@@ -0,0 +1,49 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Str;
return new class extends Migration
{
public function up(): void
{
Schema::table('users', function (Blueprint $table) {
if (!Schema::hasColumn('users', 'referral_code')) {
$table->string('referral_code', 12)->nullable()->unique()->after('uuid');
}
if (!Schema::hasColumn('users', 'referred_by')) {
$table->foreignId('referred_by')->nullable()->after('referral_code')
->constrained('users')->nullOnDelete();
}
});
// Backfill a unique referral code for existing users
$existing = DB::table('users')->whereNull('referral_code')->pluck('id');
$used = DB::table('users')->whereNotNull('referral_code')->pluck('referral_code')->all();
$used = array_flip($used);
foreach ($existing as $id) {
do {
$code = strtoupper(Str::random(8));
} while (isset($used[$code]));
$used[$code] = true;
DB::table('users')->where('id', $id)->update(['referral_code' => $code]);
}
}
public function down(): void
{
Schema::table('users', function (Blueprint $table) {
if (Schema::hasColumn('users', 'referred_by')) {
$table->dropForeign(['referred_by']);
$table->dropColumn('referred_by');
}
if (Schema::hasColumn('users', 'referral_code')) {
$table->dropColumn('referral_code');
}
});
}
};