diff --git a/app/Console/Commands/ImportBulgarianLeadingTeachers.php b/app/Console/Commands/ImportBulgarianLeadingTeachers.php new file mode 100644 index 000000000..82123e693 --- /dev/null +++ b/app/Console/Commands/ImportBulgarianLeadingTeachers.php @@ -0,0 +1,128 @@ + + */ + private array $teachers = [ + ['firstname' => 'Desislava', 'lastname' => 'Dimitrova', 'email' => 'd_dimitrova@sukim.eu', 'tag' => 'BG-Ddimitrova-001'], + ['firstname' => 'Desislava', 'lastname' => 'Tsokova', 'email' => 'tsokovadesi@gmail.com', 'tag' => 'BG-Dtsokova-002'], + ['firstname' => 'Deyana', 'lastname' => 'Peykova', 'email' => 'deyana@mail.bg', 'tag' => 'BG-Dpeykova-003'], + ['firstname' => 'Eleonora', 'lastname' => 'Pavlova', 'email' => 'eleonora.pavlova@mgberon.com', 'tag' => 'BG-Epavlova-004'], + ['firstname' => 'Elka', 'lastname' => 'Ivanova', 'email' => 'elka_ivanova@abv.bg', 'tag' => 'BG-Eivanova-005'], + ['firstname' => 'Elza', 'lastname' => 'Licheva', 'email' => 'elicheva@abv.bg', 'tag' => 'BG-Elicheva-006'], + ['firstname' => 'Ivelina', 'lastname' => 'Temelkova', 'email' => 'itemelkova@119su.bg', 'tag' => 'BG-Itemelkova-007'], + ['firstname' => 'Lyudmil', 'lastname' => 'Bonev', 'email' => 'lkbonev72@gmail.com', 'tag' => 'BG-Lbonev-008'], + ['firstname' => 'Maria', 'lastname' => 'Chakurova', 'email' => 'mimmich11@abv.bg', 'tag' => 'BG-Mchakurova-009'], + ['firstname' => 'Maria', 'lastname' => 'Kirilova', 'email' => 'eg.m.kirilova@gmail.com', 'tag' => 'BG-Mkirilova-010'], + ['firstname' => 'Mariana', 'lastname' => 'Markova-Petkova', 'email' => 'mariyana.markova@zaimov-pl.com', 'tag' => 'BG-MMarkovaPetrova-011'], + ['firstname' => 'Marin', 'lastname' => 'Ivanov Popov', 'email' => 'm.i.popov@gmail.com', 'tag' => 'BG-Mpopov-012'], + ['firstname' => 'Natalia', 'lastname' => 'Stankova', 'email' => 'nstankova579@gmail.com', 'tag' => 'BG-Nstankova-013'], + ['firstname' => 'Nedyalka', 'lastname' => 'Yordanova', 'email' => 'n.yordanova@pgmett.com', 'tag' => 'BG-Nyordanova-014'], + ['firstname' => 'Neli', 'lastname' => 'Filipova', 'email' => 'neli.philipova@2su.bg', 'tag' => 'BG-Nphilipova-015'], + ['firstname' => 'Neli', 'lastname' => 'Tikhomirova', 'email' => 'tihomirova@mg-babatonka.bg', 'tag' => 'BG-Ntihomirova-016'], + ['firstname' => 'Rositsa', 'lastname' => 'Boneva', 'email' => 'boneva.r@nfsg-sofia.org', 'tag' => 'BG-Rboneva-017'], + ['firstname' => 'Rositsa', 'lastname' => 'Yurukova', 'email' => 'rositsa.yurukova@bps-edu.org', 'tag' => 'BG-Ryurukova-018'], + ['firstname' => 'Sevdie', 'lastname' => 'Aliyeva', 'email' => 'sevdi_75@abv.bg', 'tag' => 'BG-Saliyeva-019'], + ['firstname' => 'Valya', 'lastname' => 'Garbacheva', 'email' => 'valya.garbacheva@edu.mon.bg', 'tag' => 'BG-VGArbacheva-020'], + ['firstname' => 'Vanya', 'lastname' => 'Krasteva Stefanova', 'email' => 'stefanovavania@abv.bg', 'tag' => 'BG-Vstefanova-021'], + ['firstname' => 'Yordanka', 'lastname' => 'Mladenova', 'email' => 'iordi65@abv.bg', 'tag' => 'BG-Ymladenova-022'], + ['firstname' => 'Ирина', 'lastname' => 'Христова Стойкова', 'email' => 'istojkova@gmail.com', 'tag' => 'BG-Istojkova-023'], + ['firstname' => 'Kichka', 'lastname' => 'Petrova', 'email' => 'kiki_petrova@abv.bg', 'tag' => 'BG-Kpetrova-024'], + ['firstname' => 'Petya', 'lastname' => 'Kostova-Zheleva', 'email' => 'pepi_geleva@abv.bg', 'tag' => 'BG-Pgeleva-025'], + ['firstname' => 'Ivelina', 'lastname' => 'Markova-Kenarova', 'email' => 'iva80_stm@abv.bg', 'tag' => 'BG-IMarkovaKenarova-026'], + ]; + + public function handle(): int + { + $dryRun = (bool) $this->option('dry-run'); + + $role = Role::where('name', 'leading teacher')->first(); + if (! $role) { + $this->error("Role 'leading teacher' does not exist."); + + return self::FAILURE; + } + + $created = 0; + $updated = 0; + $roleAssigned = 0; + + foreach ($this->teachers as $teacher) { + $email = strtolower(trim($teacher['email'])); + $existing = User::withTrashed()->where('email', $email)->first(); + + if ($dryRun) { + $action = $existing ? 'update' : 'create'; + $this->line("[{$action}] {$email} → {$teacher['tag']}"); + $existing ? $updated++ : $created++; + + if (! $existing || ! $existing->hasRole('leading teacher')) { + $roleAssigned++; + } + + continue; + } + + if ($existing) { + if ($existing->trashed()) { + $existing->restore(); + } + + $existing->firstname = $teacher['firstname']; + $existing->lastname = $teacher['lastname']; + $existing->country_iso = 'BG'; + $existing->tag = $teacher['tag']; + $existing->save(); + $user = $existing; + $updated++; + } else { + $user = new User(); + $user->firstname = $teacher['firstname']; + $user->lastname = $teacher['lastname']; + $user->username = Str::slug($teacher['firstname'].'-'.$teacher['lastname']).'-'.Str::random(4); + $user->email = $email; + $user->password = Hash::make(Str::random(40)); + $user->country_iso = 'BG'; + $user->tag = $teacher['tag']; + $user->privacy = true; + $user->receive_emails = true; + $user->consent_given_at = now(); + $user->email_verified_at = now(); + $user->avatar_path = 'avatars/default.png'; + $user->magic_key = random_int(100000, 999999); + $user->save(); + $created++; + } + + if (! $user->hasRole('leading teacher')) { + $user->assignRole($role); + $roleAssigned++; + } + + $this->info("OK {$email} → {$teacher['tag']}"); + } + + $prefix = $dryRun ? 'Dry-run' : 'Done'; + $this->info("{$prefix}: created={$created}, updated={$updated}, role_assigned={$roleAssigned}"); + + return self::SUCCESS; + } +} diff --git a/tests/Feature/ImportBulgarianLeadingTeachersTest.php b/tests/Feature/ImportBulgarianLeadingTeachersTest.php new file mode 100644 index 000000000..1e0435727 --- /dev/null +++ b/tests/Feature/ImportBulgarianLeadingTeachersTest.php @@ -0,0 +1,68 @@ +seed('RolesAndPermissionsSeeder'); + $this->seed('LeadingTeacherRoleSeeder'); + Country::factory()->create(['iso' => 'BG', 'name' => 'Bulgaria']); + } + + #[Test] + public function dry_run_does_not_write_users(): void + { + $this->artisan('leading-teachers:import-bulgaria', ['--dry-run' => true]) + ->assertSuccessful(); + + $this->assertSame(0, User::where('tag', 'like', 'BG-%')->count()); + } + + #[Test] + public function import_creates_users_with_tags_and_role(): void + { + $this->artisan('leading-teachers:import-bulgaria') + ->assertSuccessful(); + + $this->assertSame(26, User::role('leading teacher')->where('country_iso', 'BG')->whereNotNull('tag')->count()); + + $user = User::where('email', 'd_dimitrova@sukim.eu')->first(); + $this->assertNotNull($user); + $this->assertSame('BG-Ddimitrova-001', $user->tag); + $this->assertTrue($user->hasRole('leading teacher')); + $this->assertSame('BG', $user->country_iso); + } + + #[Test] + public function import_updates_existing_user_tag_and_is_idempotent(): void + { + $existing = User::factory()->create([ + 'email' => 'd_dimitrova@sukim.eu', + 'firstname' => 'Old', + 'lastname' => 'Name', + 'country_iso' => 'BG', + 'tag' => null, + ]); + + $this->artisan('leading-teachers:import-bulgaria')->assertSuccessful(); + $this->artisan('leading-teachers:import-bulgaria')->assertSuccessful(); + + $existing->refresh(); + $this->assertSame('Desislava', $existing->firstname); + $this->assertSame('Dimitrova', $existing->lastname); + $this->assertSame('BG-Ddimitrova-001', $existing->tag); + $this->assertTrue($existing->hasRole('leading teacher')); + $this->assertSame(1, User::where('email', 'd_dimitrova@sukim.eu')->count()); + } +}