diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php index beb373e..8827472 100644 --- a/app/Http/Controllers/UserController.php +++ b/app/Http/Controllers/UserController.php @@ -210,14 +210,22 @@ public function register(Request $request) 'method' => 'string|in:code,link|nullable', 'birthday' => 'date|nullable', 'gender' => ['integer', 'nullable', Rule::in(User::GENDERS)], + 'referrer_code' => ['string', 'nullable', 'exists:users,referral_code'], ]); - + $method = $data['method'] ?? 'link'; unset($data['method']); // Extract and remove package_name $packageNameValue = $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'])) { $data['mobile'] = MobileNumberHelper::formatMobile($data['mobile']); diff --git a/app/Models/User.php b/app/Models/User.php index ed3c9cb..60aa670 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -3,6 +3,7 @@ namespace App\Models; use App\Traits\HasUuid; +use App\Traits\HasReferralCode; use DateTimeInterface; use EloquentFilter\Filterable; use Illuminate\Database\Eloquent\Factories\HasFactory; @@ -13,7 +14,7 @@ use Illuminate\Support\Str; class User extends Authenticatable { - use HasApiTokens, HasFactory, Notifiable, HasUuid, Filterable; + use HasApiTokens, HasFactory, Notifiable, HasUuid, HasReferralCode, Filterable; const GENDERS = [ 'male' => 1, @@ -61,6 +62,16 @@ public function otpTokens() 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() { return $this->hasMany(Transaction::class); diff --git a/app/Traits/HasReferralCode.php b/app/Traits/HasReferralCode.php new file mode 100644 index 0000000..24b42fa --- /dev/null +++ b/app/Traits/HasReferralCode.php @@ -0,0 +1,26 @@ +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; + } +} diff --git a/database/migrations/2026_06_06_000000_add_referral_code_and_referred_by_to_users_table.php b/database/migrations/2026_06_06_000000_add_referral_code_and_referred_by_to_users_table.php new file mode 100644 index 0000000..44fe0af --- /dev/null +++ b/database/migrations/2026_06_06_000000_add_referral_code_and_referred_by_to_users_table.php @@ -0,0 +1,49 @@ +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'); + } + }); + } +};