Files
usher-manage-stack/app/Console/Commands/ImportMembers.php
2025-11-20 23:21:05 +08:00

147 lines
4.5 KiB
PHP

<?php
namespace App\Console\Commands;
use App\Mail\MemberActivationMail;
use App\Models\Member;
use App\Models\User;
use App\Support\AuditLogger;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Password;
use Illuminate\Support\Str;
class ImportMembers extends Command
{
protected $signature = 'members:import {path : CSV file path}';
protected $description = 'Import members from a CSV file';
public function handle(): int
{
$path = $this->argument('path');
if (! is_file($path)) {
$this->error("File not found: {$path}");
return static::FAILURE;
}
$handle = fopen($path, 'r');
if (! $handle) {
$this->error("Unable to open file: {$path}");
return static::FAILURE;
}
$header = fgetcsv($handle);
if (! $header) {
$this->error('CSV file is empty.');
fclose($handle);
return static::FAILURE;
}
$header = array_map('trim', $header);
$expected = [
'full_name',
'email',
'phone',
'address_line_1',
'address_line_2',
'city',
'postal_code',
'emergency_contact_name',
'emergency_contact_phone',
'membership_started_at',
'membership_expires_at',
];
foreach ($expected as $column) {
if (! in_array($column, $header, true)) {
$this->error("Missing required column: {$column}");
fclose($handle);
return static::FAILURE;
}
}
$indexes = array_flip($header);
$createdUsers = 0;
$updatedMembers = 0;
while (($row = fgetcsv($handle)) !== false) {
$email = trim($row[$indexes['email']] ?? '');
if ($email === '') {
continue;
}
$fullName = trim($row[$indexes['full_name']] ?? '');
$nationalId = trim($row[$indexes['national_id']] ?? '');
$phone = trim($row[$indexes['phone']] ?? '');
$started = trim($row[$indexes['membership_started_at']] ?? '');
$expires = trim($row[$indexes['membership_expires_at']] ?? '');
$address1 = trim($row[$indexes['address_line_1']] ?? '');
$address2 = trim($row[$indexes['address_line_2']] ?? '');
$city = trim($row[$indexes['city']] ?? '');
$postal = trim($row[$indexes['postal_code']] ?? '');
$emergencyName = trim($row[$indexes['emergency_contact_name']] ?? '');
$emergencyPhone = trim($row[$indexes['emergency_contact_phone']] ?? '');
$user = User::where('email', $email)->first();
$isNewUser = false;
if (! $user) {
$user = User::create([
'name' => $fullName !== '' ? $fullName : $email,
'email' => $email,
'password' => Str::random(32),
]);
$isNewUser = true;
$createdUsers++;
}
$member = Member::updateOrCreate(
['user_id' => $user->id],
[
'full_name' => $fullName !== '' ? $fullName : $user->name,
'email' => $email,
'national_id' => $nationalId !== '' ? $nationalId : null,
'phone' => $phone !== '' ? $phone : null,
'address_line_1' => $address1 ?: null,
'address_line_2' => $address2 ?: null,
'city' => $city ?: null,
'postal_code' => $postal ?: null,
'emergency_contact_name' => $emergencyName ?: null,
'emergency_contact_phone' => $emergencyPhone ?: null,
'membership_started_at' => $started !== '' ? $started : null,
'membership_expires_at' => $expires !== '' ? $expires : null,
],
);
$updatedMembers++;
if ($isNewUser) {
$token = Password::createToken($user);
Mail::to($user)->queue(new MemberActivationMail($user, $token));
AuditLogger::log('user.activation_link_sent', $user, [
'email' => $user->email,
]);
}
}
fclose($handle);
$this->info("Users created: {$createdUsers}");
$this->info("Members imported/updated: {$updatedMembers}");
return static::SUCCESS;
}
}