feat: referral_code
This commit is contained in:
@@ -210,14 +210,22 @@ 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';
|
||||||
unset($data['method']);
|
unset($data['method']);
|
||||||
|
|
||||||
// Extract and remove package_name
|
// Extract and remove package_name
|
||||||
$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']);
|
||||||
|
|||||||
+12
-1
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
+49
@@ -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');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user