diff --git a/app/Console/Commands/SyncSurveyUsers.php b/app/Console/Commands/SyncSurveyUsers.php new file mode 100644 index 0000000..3f82fce --- /dev/null +++ b/app/Console/Commands/SyncSurveyUsers.php @@ -0,0 +1,69 @@ +option('token') ?: config('services.approagency.token'); + + if (empty($token)) { + $this->error('Provide --token= or set APPROAGENCY_ADMIN_TOKEN in .env'); + return 1; + } + + $users = User::whereNull('first_name') + ->whereNotNull('mobile') + ->get(); + + $this->info("Found {$users->count()} users with missing first_name. Syncing..."); + + $synced = 0; + $failed = 0; + + foreach ($users as $user) { + try { + $response = Http::withToken($token) + ->get('https://api.approagency.ir/api/admin/users', [ + 'mobile' => $user->mobile, + 'per_page' => 1, + ]); + + if ($response->successful()) { + $data = $response->json('data.0'); + if ($data) { + $user->update([ + 'first_name' => $data['first_name'] ?? $user->first_name, + 'last_name' => $data['last_name'] ?? $user->last_name, + 'age' => $data['age'] ?? $user->age, + 'gender' => $data['gender'] ?? $user->gender, + 'birthday' => $data['birthday'] ?? $user->birthday, + 'identifier' => $data['uuid'] ?? $user->identifier, + ]); + $this->line(" synced: {$user->mobile} → {$data['first_name'] ?? 'null'}"); + $synced++; + } + } else { + $this->warn(" skip: {$user->mobile} (HTTP {$response->status()})"); + $failed++; + } + } catch (\Exception $e) { + $this->error(" failed: {$user->mobile} — {$e->getMessage()}"); + $failed++; + } + + usleep(200000); // 200ms delay to avoid rate limits + } + + $this->info("Done. Synced: {$synced}, Failed: {$failed}"); + return 0; + } +} diff --git a/app/Http/Controllers/SurveyQuestionController.php b/app/Http/Controllers/SurveyQuestionController.php index 1654d58..7707740 100644 --- a/app/Http/Controllers/SurveyQuestionController.php +++ b/app/Http/Controllers/SurveyQuestionController.php @@ -9,6 +9,7 @@ use App\Models\User; use Illuminate\Http\Request; use Illuminate\Support\Facades\DB; +use Illuminate\Support\Facades\Http; use Illuminate\Validation\ValidationException; class SurveyQuestionController extends Controller @@ -127,6 +128,34 @@ public function adminUserShow($identifier) return response()->json($user); } + // ADMIN: update a user's profile fields from approagency data. + public function adminUserUpdate(Request $request, $identifier) + { + if (is_numeric($identifier)) { + $user = User::where('id', $identifier)->first(); + } else { + $user = User::where('identifier', $identifier)->first(); + } + + if (!$user) { + abort(404); + } + + $data = $request->validate([ + 'first_name' => 'nullable|string', + 'last_name' => 'nullable|string', + 'age' => 'nullable|integer', + 'gender' => 'nullable|integer', + 'birthday' => 'nullable|string', + 'identifier' => 'nullable|string', + 'email' => 'nullable|email', + ]); + + $user->update(array_filter($data, fn ($v) => !is_null($v))); + + return response()->json($user); + } + // ADMIN: clean aggregated results — per option vote counts & percentages, no raw rows. // Pass an $id for one question, omit it for all questions. public function adminAnalytics($id = null) diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php index 5376763..3479c8e 100644 --- a/app/Http/Controllers/UserController.php +++ b/app/Http/Controllers/UserController.php @@ -66,21 +66,31 @@ public function loginV2(Request $request) 'email' => $response['email'], 'identifier' => $response['uuid'] ?? null, 'password' => config('app.default_password'), - // 'name' => trim(($response['first_name'] ?? '') . ' ' . ($response['last_name'] ?? '')), 'mobile' => $mobile, 'first_name' => $response['first_name'] ?? null, 'last_name' => $response['last_name'] ?? null, + 'age' => $response['age'] ?? null, + 'gender' => $response['gender'] ?? null, + 'birthday' => $response['birthday'] ?? null, 'referral_code' => $response['referral_code'] ?? null, ]); } else { - // Only update name and mobile for existing user // Keep the local identifier aligned with the current approagency uuid // (e.g. when the user was matched by mobile, not identifier). $user->identifier = $response['uuid'] ?? $user->identifier; - $user->first_name = $response['first_name'] ?? $user->first_name; - $user->last_name = $response['last_name'] ?? $user->last_name; - // $user->name = trim(($response['first_name'] ?? '') . ' ' . ($response['last_name'] ?? '')); + + // Sync names — update if the response has a non-null, non-empty value + if (!empty($response['first_name'])) { + $user->first_name = $response['first_name']; + } + if (!empty($response['last_name'])) { + $user->last_name = $response['last_name']; + } + $user->mobile = $mobile ?? $user->mobile; + $user->age = $response['age'] ?? $user->age; + $user->gender = $response['gender'] ?? $user->gender; + $user->birthday = $response['birthday'] ?? $user->birthday; $user->referral_code = $response['referral_code'] ?? $user->referral_code; $user->save(); } @@ -134,15 +144,27 @@ private function syncUserFromStatus(array $response, ?User $user = null): User 'mobile' => $mobile, 'first_name' => $response['first_name'] ?? null, 'last_name' => $response['last_name'] ?? null, + 'age' => $response['age'] ?? null, + 'gender' => $response['gender'] ?? null, + 'birthday' => $response['birthday'] ?? null, 'referral_code' => $response['referral_code'] ?? null, 'email_verified_at' => $response['email_verified_at'] ?? null ]); } else { // update existing $user->identifier = $response['uuid'] ?? $user->identifier; - $user->first_name = $response['first_name'] ?? $user->first_name; - $user->last_name = $response['last_name'] ?? $user->last_name; + + if (!empty($response['first_name'])) { + $user->first_name = $response['first_name']; + } + if (!empty($response['last_name'])) { + $user->last_name = $response['last_name']; + } + $user->mobile = $mobile ?? $user->mobile; + $user->age = $response['age'] ?? $user->age; + $user->gender = $response['gender'] ?? $user->gender; + $user->birthday = $response['birthday'] ?? $user->birthday; $user->referral_code = $response['referral_code'] ?? $user->referral_code; $user->email_verified_at = $response['email_verified_at'] ?? $user->email_verified_at; $user->save(); diff --git a/routes/api.php b/routes/api.php index 6f96402..376af99 100644 --- a/routes/api.php +++ b/routes/api.php @@ -169,6 +169,7 @@ // User list + detail for survey admin Route::get('/admin/survey-users', [SurveyQuestionController::class, 'adminUsers']); Route::get('/admin/survey-users/{id}', [SurveyQuestionController::class, 'adminUserShow']); + Route::patch('/admin/survey-users/{id}', [SurveyQuestionController::class, 'adminUserUpdate']); }); // User: answer + read questions with their own answers only. Route::get('/survey-questions/suggested-media', [SurveyQuestionController::class, 'suggestedMedia']);