feat: add referral_code
This commit is contained in:
@@ -140,6 +140,85 @@ public function subscribeUser(Request $request, $identifier)
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* List users who reached the referral invite target (کد معرف) and have
|
||||
* not yet been granted their free-month subscription.
|
||||
*/
|
||||
public function pendingReferralRewards(Request $request)
|
||||
{
|
||||
$target = User::REFERRAL_SUBSCRIPTION_TARGET;
|
||||
|
||||
$users = User::withCount('referrals')
|
||||
->whereNull('referral_subscription_granted_at')
|
||||
->having('referrals_count', '>=', $target)
|
||||
->orderByDesc('referrals_count')
|
||||
->get(['id', 'uuid', 'first_name', 'last_name', 'email', 'mobile', 'referral_code']);
|
||||
|
||||
return response()->json([
|
||||
'subscription_target' => $target,
|
||||
'data' => $users->map(fn ($u) => [
|
||||
'id' => $u->id,
|
||||
'uuid' => $u->uuid,
|
||||
'name' => trim($u->first_name . ' ' . $u->last_name),
|
||||
'email' => $u->email,
|
||||
'mobile' => $u->mobile,
|
||||
'referral_code' => $u->referral_code,
|
||||
'successful_invites' => $u->referrals_count,
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Grant the free-month subscription to a user who reached the referral
|
||||
* invite target. Defaults to the meditation package's monthly product,
|
||||
* overridable via product_id. Marks the grant so it happens only once.
|
||||
*/
|
||||
public function fulfillReferralReward(Request $request, $userId)
|
||||
{
|
||||
$data = $request->validate([
|
||||
'product_id' => 'integer|nullable',
|
||||
]);
|
||||
|
||||
if (!$user = User::find($userId)) {
|
||||
return response()->json(['message' => 'user not found'], 404);
|
||||
}
|
||||
|
||||
if ($user->referral_subscription_granted_at) {
|
||||
return response()->json(['message' => 'referral subscription already granted'], 400);
|
||||
}
|
||||
|
||||
if ($user->referrals()->count() < User::REFERRAL_SUBSCRIPTION_TARGET) {
|
||||
return response()->json(['message' => 'user has not reached the referral target yet'], 400);
|
||||
}
|
||||
|
||||
// Resolve which monthly product to grant
|
||||
if (!empty($data['product_id'])) {
|
||||
$product = Product::where('id', $data['product_id'])->first();
|
||||
} else {
|
||||
$package = PackageName::where('name', User::REFERRAL_PACKAGE_NAME)->first();
|
||||
$product = $package
|
||||
? Product::where('package_name_id', $package->id)
|
||||
->where('type', Product::TYPES['monthly'])
|
||||
->first()
|
||||
: null;
|
||||
}
|
||||
|
||||
if (!$product) {
|
||||
return response()->json(['message' => 'monthly product not found'], 404);
|
||||
}
|
||||
|
||||
$product->buy($user);
|
||||
|
||||
$user->referral_subscription_granted_at = now();
|
||||
$user->save();
|
||||
|
||||
return response()->json([
|
||||
'message' => 'referral subscription granted',
|
||||
'user_id' => $user->id,
|
||||
'product_id' => $product->id,
|
||||
]);
|
||||
}
|
||||
|
||||
public function unsubscribeUser(Request $request, $identifier)
|
||||
{
|
||||
$data = $request->validate([
|
||||
|
||||
@@ -638,6 +638,10 @@ public function status(Request $request)
|
||||
->first();
|
||||
}
|
||||
|
||||
// Expose the referrer's uuid so downstream apps can resolve the
|
||||
// referral relationship (کد معرف) against their own local user.
|
||||
$user['referrer_uuid'] = $user->referred_by ? optional($user->referrer)->uuid : null;
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,9 +20,16 @@ class User extends Authenticatable
|
||||
'male' => 1,
|
||||
'female' => 2,
|
||||
];
|
||||
|
||||
// Referral program (کد معرف): successful invites needed for a free month,
|
||||
// and the app whose monthly product is granted as the reward.
|
||||
const REFERRAL_SUBSCRIPTION_TARGET = 10;
|
||||
const REFERRAL_PACKAGE_NAME = 'com.approagency.meditation';
|
||||
|
||||
protected $guarded = [];
|
||||
protected $casts = [
|
||||
'mobile_verified_at' => 'datetime',
|
||||
'referral_subscription_granted_at' => 'datetime',
|
||||
];
|
||||
protected $hidden = [
|
||||
'password',
|
||||
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
// When the referral free-month subscription was granted (null = not yet).
|
||||
if (!Schema::hasColumn('users', 'referral_subscription_granted_at')) {
|
||||
$table->timestamp('referral_subscription_granted_at')->nullable()->after('referred_by');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
if (Schema::hasColumn('users', 'referral_subscription_granted_at')) {
|
||||
$table->dropColumn('referral_subscription_granted_at');
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -95,6 +95,9 @@
|
||||
Route::get('/users/{mobile}/status-v1', 'getUserStatusV1');
|
||||
Route::put('/users/{mobile}/status', 'subscribeUser');
|
||||
Route::delete('/users/{mobile}/status', 'unsubscribeUser');
|
||||
// Referral free-month rewards (کد معرف)
|
||||
Route::get('/referral-rewards', 'pendingReferralRewards');
|
||||
Route::post('/referral-rewards/{user}/fulfill', 'fulfillReferralReward');
|
||||
});
|
||||
});
|
||||
///promotions
|
||||
|
||||
Reference in New Issue
Block a user