diff --git a/app/Domains/Auth/Models/User.php b/app/Domains/Auth/Models/User.php index 329af25..3dbf641 100644 --- a/app/Domains/Auth/Models/User.php +++ b/app/Domains/Auth/Models/User.php @@ -13,6 +13,7 @@ use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Database\Eloquent\Relations\HasMany; +use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; use Laravel\Sanctum\HasApiTokens; @@ -22,7 +23,7 @@ use Laravel\Sanctum\HasApiTokens; class User extends Authenticatable { /** @use HasFactory */ - use HasApiTokens, HasFactory, Notifiable; + use HasApiTokens, HasFactory, Notifiable, SoftDeletes; protected $attributes = [ 'rol_codigo' => RoleCode::User->value, diff --git a/app/Domains/Staff/Services/StaffService.php b/app/Domains/Staff/Services/StaffService.php index fc7c445..4039cb5 100644 --- a/app/Domains/Staff/Services/StaffService.php +++ b/app/Domains/Staff/Services/StaffService.php @@ -94,7 +94,12 @@ class StaffService public function delete(Tenant $tenant, int $staffId): void { - $this->find($tenant, $staffId)->delete(); + $staff = $this->find($tenant, $staffId); + + DB::transaction(function () use ($staff): void { + $staff->tokens()->delete(); + $staff->delete(); + }); } public function find(Tenant $tenant, int $staffId): User diff --git a/app/Domains/Ticket/Models/Ticket.php b/app/Domains/Ticket/Models/Ticket.php index 8efc786..ab71c90 100644 --- a/app/Domains/Ticket/Models/Ticket.php +++ b/app/Domains/Ticket/Models/Ticket.php @@ -78,7 +78,7 @@ class Ticket extends Model /** @return BelongsTo */ public function scannerUser(): BelongsTo { - return $this->belongsTo(User::class, 'scanner_user_id'); + return $this->belongsTo(User::class, 'scanner_user_id')->withTrashed(); } /** @return BelongsTo */ diff --git a/app/Domains/Ticket/Services/AdminAppTicketService.php b/app/Domains/Ticket/Services/AdminAppTicketService.php index 2ea0d2d..cc41319 100644 --- a/app/Domains/Ticket/Services/AdminAppTicketService.php +++ b/app/Domains/Ticket/Services/AdminAppTicketService.php @@ -293,6 +293,7 @@ class AdminAppTicketService 'id' => 'tickets.id', 'amount' => $this->purchaseItemColumnQuery('precio_unitario'), 'scanned_by' => User::query() + ->withTrashed() ->select('nombre_apellido') ->whereColumn('users.id', 'tickets.scanner_user_id'), 'product' => $tenant->codigo === 'fiesta_futbol_infantil' diff --git a/database/migrations/2026_09_03_000000_add_soft_deletes_to_users_table.php b/database/migrations/2026_09_03_000000_add_soft_deletes_to_users_table.php new file mode 100644 index 0000000..0ab6b93 --- /dev/null +++ b/database/migrations/2026_09_03_000000_add_soft_deletes_to_users_table.php @@ -0,0 +1,23 @@ +softDeletes(); + }); + + } + + public function down(): void + { + Schema::table('users', function (Blueprint $table): void { + $table->dropSoftDeletes(); + }); + } +}; diff --git a/tests/Feature/Staff/StaffControllerTest.php b/tests/Feature/Staff/StaffControllerTest.php index e7c9434..50ac709 100644 --- a/tests/Feature/Staff/StaffControllerTest.php +++ b/tests/Feature/Staff/StaffControllerTest.php @@ -2,6 +2,8 @@ namespace Tests\Feature\Staff; +use App\Domains\Attachable\Enums\AttachmentType; +use App\Domains\Attachable\Models\Attachment; use App\Domains\Auth\Models\ResetPasswordAttempt; use App\Domains\Auth\Models\User; use App\Domains\Authorization\Enums\RoleCode; @@ -9,9 +11,11 @@ use App\Domains\Catalog\Models\Category; use App\Domains\Notification\Events\PasswordResetRequested; use App\Domains\Tenant\Models\Tenant; use App\Domains\Tenant\Models\WebsiteType; +use App\Domains\Ticket\Models\Ticket; use Database\Seeders\AuthorizationSeeder; use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Support\Facades\Event; +use Illuminate\Support\Str; use Laravel\Sanctum\Sanctum; use Tests\TestCase; @@ -30,11 +34,21 @@ class StaffControllerTest extends TestCase Event::fake([PasswordResetRequested::class]); $this->seed(AuthorizationSeeder::class); WebsiteType::query()->create(['codigo' => 'onticket', 'nombre' => 'OnTicket']); + $headerLogo = $this->createAttachment('header.png'); + $footerLogo = $this->createAttachment('footer.png'); $this->tenant = Tenant::query()->create([ 'codigo' => 'acme', 'nombre' => 'Acme', 'dominio' => 'acme.test', 'website_type_code' => 'onticket', + 'primary_color' => '#111111', + 'secondary_color' => '#222222', + 'danger_color' => '#cc0000', + 'success_color' => '#008800', + 'header_bg_color' => '#ffffff', + 'footer_bg_color' => '#ffffff', + 'header_logo_id' => $headerLogo->id, + 'footer_logo_id' => $footerLogo->id, ]); $this->admin = User::factory()->create([ 'rol_codigo' => RoleCode::AdminApp->value, @@ -92,8 +106,33 @@ class StaffControllerTest extends TestCase 'categoria_id' => $firstCategory->id, ]); + $ticket = Ticket::query()->create([ + 'tenant_code' => $this->tenant->codigo, + 'ticket' => (string) Str::uuid(), + 'user_id' => $this->admin->id, + 'used_at' => now(), + 'scanner_user_id' => $staffId, + ]); + $accessTokenId = User::query() + ->findOrFail($staffId) + ->createToken('scanner', ['scanner']) + ->accessToken + ->getKey(); + $this->deleteJson("/api/v1/adminapp/tenant/staff/{$staffId}")->assertNoContent(); - $this->assertDatabaseMissing('users', ['id' => $staffId]); + $this->assertSoftDeleted('users', ['id' => $staffId]); + $this->assertDatabaseMissing('personal_access_tokens', ['id' => $accessTokenId]); + $this->assertDatabaseHas('category_scanners', [ + 'user_id' => $staffId, + 'categoria_id' => $secondCategory->id, + ]); + $this->assertSame($staffId, $ticket->fresh()->scanner_user_id); + $this->assertSame('Ada Byron', $ticket->fresh()->scannerUser?->nombre_apellido); + + $this->getJson('/api/v1/adminapp/tenant/staff') + ->assertOk() + ->assertJsonCount(0, 'data'); + } public function test_admin_cannot_assign_another_tenants_category(): void @@ -104,6 +143,14 @@ class StaffControllerTest extends TestCase 'nombre' => 'Other', 'dominio' => 'other.test', 'website_type_code' => 'onticket', + 'primary_color' => '#111111', + 'secondary_color' => '#222222', + 'danger_color' => '#cc0000', + 'success_color' => '#008800', + 'header_bg_color' => '#ffffff', + 'footer_bg_color' => '#ffffff', + 'header_logo_id' => $this->tenant->header_logo_id, + 'footer_logo_id' => $this->tenant->footer_logo_id, ]); $foreignCategory = Category::query()->create([ 'tenant_code' => $otherTenant->codigo, @@ -183,6 +230,16 @@ class StaffControllerTest extends TestCase $this->getJson('/api/v1/adminapp/tenant/staff')->assertForbidden(); } + private function createAttachment(string $filename): Attachment + { + return Attachment::query()->create([ + 'path' => "test/{$filename}", + 'filename' => $filename, + 'type' => AttachmentType::Image, + 'mime_type' => 'image/png', + ]); + } + private function createCategory(string $name): Category { return Category::query()->create([