From 5fe41a45576438755877bf7dee8df74cb1ab8666 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 11 Feb 2026 11:10:17 -0600 Subject: [PATCH] =?UTF-8?q?Actualizaci=C3=B3n=20de=20moelo=20user=20y=20re?= =?UTF-8?q?laci=C3=B3n=20many=20con=20asistencias,=20creaci=C3=B3n=20del?= =?UTF-8?q?=20modelo=20de=20asistencia=20y=20control=20por=20middleware=20?= =?UTF-8?q?y=20autenticaci=C3=B3n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Actions/Fortify/CreateNewUser.php | 53 ++++-- app/Http/Controllers/CodeController.php | 24 +++ app/Http/Controllers/ProspectoController.php | 62 ++++--- app/Livewire/CodeScanner.php | 30 ++++ app/Livewire/DataProspecto.php | 3 +- app/Livewire/ModalProspecto.php | 29 +++- app/Models/Code.php | 20 +++ app/Models/User.php | 18 +- app/Providers/FortifyServiceProvider.php | 9 + .../0001_01_01_000000_create_users_table.php | 1 + .../2026_02_05_194540_create_codes_table.php | 31 ++++ ...26_02_11_165653_create_area_code_table.php | 28 +++ database/seeders/AreaCodeSeeder.php | 33 ++++ database/seeders/DatabaseSeeder.php | 1 + database/seeders/RoleSeeder.php | 10 +- database/seeders/UserSeeder.php | 1 + database/seeders/prospectoStatusSeeder.php | 5 +- resources/views/auth/register.blade.php | 22 ++- resources/views/code/index.blade.php | 23 +++ .../views/layouts/_partials/code.blade.php | 3 + .../views/layouts/_partials/menu.blade.php | 161 ++++-------------- resources/views/layouts/landing.blade.php | 57 +++++-- .../views/livewire/code-scanner.blade.php | 103 +++++++++++ resources/views/prospecto/index.blade.php | 29 ---- routes/web.php | 36 ++-- 25 files changed, 545 insertions(+), 247 deletions(-) create mode 100644 app/Http/Controllers/CodeController.php create mode 100644 app/Livewire/CodeScanner.php create mode 100644 app/Models/Code.php create mode 100644 database/migrations/2026_02_05_194540_create_codes_table.php create mode 100644 database/migrations/2026_02_11_165653_create_area_code_table.php create mode 100644 database/seeders/AreaCodeSeeder.php create mode 100644 resources/views/code/index.blade.php create mode 100644 resources/views/layouts/_partials/code.blade.php create mode 100644 resources/views/livewire/code-scanner.blade.php diff --git a/app/Actions/Fortify/CreateNewUser.php b/app/Actions/Fortify/CreateNewUser.php index 566e51df..1c3d4ede 100644 --- a/app/Actions/Fortify/CreateNewUser.php +++ b/app/Actions/Fortify/CreateNewUser.php @@ -3,33 +3,64 @@ namespace App\Actions\Fortify; use App\Models\User; +use App\Models\Prospecto; +use Laravel\Jetstream\Jetstream; use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Validator; +use Illuminate\Validation\ValidationException; use Laravel\Fortify\Contracts\CreatesNewUsers; -use Laravel\Jetstream\Jetstream; class CreateNewUser implements CreatesNewUsers { use PasswordValidationRules; - /** - * Validate and create a newly registered user. - * - * @param array $input - */ - public function create(array $input): User + public function create(array $input) { Validator::make($input, [ 'name' => ['required', 'string', 'max:255'], 'email' => ['required', 'string', 'email', 'max:255', 'unique:users'], + 'telefono' => ['required', 'digits:10', 'unique:users,telefono'], 'password' => $this->passwordRules(), 'terms' => Jetstream::hasTermsAndPrivacyPolicyFeature() ? ['accepted', 'required'] : '', ])->validate(); - return User::create([ - 'name' => $input['name'], - 'email' => $input['email'], - 'password' => Hash::make($input['password']), + + + if (User::where('email', $input['email']) + ->orWhere('telefono', $input['telefono']) + ->exists()) { + + throw ValidationException::withMessages([ + 'email' => ['El correo o teléfono ya están registrados.'] + ]); + + } + + $user = User::create([ + 'name' => $input['name'], + 'email' => $input['email'], + 'telefono' => $input['telefono'], + 'direccion' => "", + 'password' => Hash::make($input['password']), + 'status' => 1 ]); + + $user->roles()->sync([4]); + $user->plantelUsuarios()->sync($input['plantels']); + + $prospecto = Prospecto::create([ + 'nivel' => 0, + 'plan_id' => 0, + 'usuario_registro' => 0, + 'ciclo' => 0, + 'turno' => 0, + 'medio' => 0, + ]); + + $prospecto->prospectos()->sync([$user->id]); + + + + return $user; } } diff --git a/app/Http/Controllers/CodeController.php b/app/Http/Controllers/CodeController.php new file mode 100644 index 00000000..89b6ccd4 --- /dev/null +++ b/app/Http/Controllers/CodeController.php @@ -0,0 +1,24 @@ +middleware('can:code.index')->only('index','show','create'); + } + + public function index() + { + // $conceptos = Concepto::where('tipo','=','3')->get(); + return view('code.index'); + } + + public function show() + { + return view('code.show'); + } +} diff --git a/app/Http/Controllers/ProspectoController.php b/app/Http/Controllers/ProspectoController.php index dfcc32e1..794bf52f 100644 --- a/app/Http/Controllers/ProspectoController.php +++ b/app/Http/Controllers/ProspectoController.php @@ -3,13 +3,10 @@ namespace App\Http\Controllers; use App\Models\User; -use App\Models\Nivel; use App\Models\Prospecto; -use Illuminate\Http\Request; use Illuminate\Routing\Controller; use Illuminate\Support\Facades\Auth; -use Spatie\Permission\Models\Permission; class ProspectoController extends Controller @@ -24,38 +21,57 @@ class ProspectoController extends Controller public function index() { $user = Auth::user(); + $plantelesUsuario = $user->plantelUsuarios->pluck('id'); - $prospectos = User::with(['prospectos' => function ($query) use ($user) { - $query->where('usuario_registro', $user->id); - }]) - ->whereHas('prospectos', function ($query) use ($user) { - $query->where('usuario_registro', $user->id); - }) - ->get(); + $prospectos = User::with(['prospectos' => function ($query) use ($user, $plantelesUsuario) { + + $query->where(function ($q) use ($user, $plantelesUsuario) { + + $q->where('usuario_registro', $user->id) + ->orWhereHas('prospectos.plantelUsuarios', function ($sub) use ($plantelesUsuario) { + $sub->whereIn('plantels.id', $plantelesUsuario); + }); + + }); + + }]) + ->whereHas('prospectos', function ($query) use ($user, $plantelesUsuario) { + + $query->where(function ($q) use ($user, $plantelesUsuario) { + + $q->where('usuario_registro', $user->id) + ->orWhereHas('prospectos.plantelUsuarios', function ($sub) use ($plantelesUsuario) { + $sub->whereIn('plantels.id', $plantelesUsuario); + }); + + }); + + }) + ->get(); return view('prospecto.index', compact('prospectos')); } public function destroy(Prospecto $prospecto) { - $user = $prospecto->prospectos()->first(); + $user = $prospecto->prospectos()->first(); - if ($user) { - $user->roles()->detach(); + if ($user) { + $user->roles()->detach(); - $user->plantelUsuarios()->detach(); + $user->plantelUsuarios()->detach(); - $prospecto->prospectos()->detach($user->id); + $prospecto->prospectos()->detach($user->id); - $user->delete(); - } + $user->delete(); + } - $prospecto->delete(); - session()->flash('swal',[ - 'icon'=>'success', - 'title'=>'Eliminado!', - 'text'=>'Se ha eliminado el registro correctamente' - ]); + $prospecto->delete(); + session()->flash('swal',[ + 'icon'=>'success', + 'title'=>'Eliminado!', + 'text'=>'Se ha eliminado el registro correctamente' + ]); return redirect()->route('prospecto.index'); } } diff --git a/app/Livewire/CodeScanner.php b/app/Livewire/CodeScanner.php new file mode 100644 index 00000000..7872d5f4 --- /dev/null +++ b/app/Livewire/CodeScanner.php @@ -0,0 +1,30 @@ +dispatch('swal', + icon: 'success', + title: 'Asistencia registrada!', + text: $lat, + timer: 2000, + confirm: false, + closeModal: true + ); + } + + public function render() + { + return view('livewire.code-scanner'); + } +} diff --git a/app/Livewire/DataProspecto.php b/app/Livewire/DataProspecto.php index 217f519a..3bec1cc2 100644 --- a/app/Livewire/DataProspecto.php +++ b/app/Livewire/DataProspecto.php @@ -121,7 +121,7 @@ class DataProspecto extends Component public function actualizarProspecto() { - $user = $this->prospecto->prospectos()->first(); + $user = $this->prospecto->prospectos()->first(); if (!$user) return; try { @@ -331,6 +331,7 @@ class DataProspecto extends Component $this->niveles = []; $this->plans = []; $this->turnos = []; + $this->conceptos = []; $this->active = "disabled"; $this->prospecto = null; diff --git a/app/Livewire/ModalProspecto.php b/app/Livewire/ModalProspecto.php index 06d2c82a..6f43b03a 100644 --- a/app/Livewire/ModalProspecto.php +++ b/app/Livewire/ModalProspecto.php @@ -68,9 +68,6 @@ class ModalProspecto extends Component $this->active = "disabled"; } - /* ------------------ EDITAR ------------------ */ - - /* ------------------ NUEVO ------------------ */ #[On('create-prospecto')] public function createProspecto() @@ -118,10 +115,16 @@ class ModalProspecto extends Component ->orWhere('telefono', $this->ptelefono) ->exists()) { - $this->dispatch('swal:error', [ - 'title' => 'Registro duplicado', - 'text' => 'El correo o teléfono ya están registrados.' - ]); + $this->dispatch('swal', + icon: 'error', + title: 'Registro duplicado', + text: 'El correo o teléfono ya están registrados.', + timer: 2000, + confirm: false, + closeModal: true + ); + + return; } @@ -149,8 +152,16 @@ class ModalProspecto extends Component $prospecto->prospectos()->sync([$user->id]); - $this->dispatch('swal:success'); - $this->dispatch('prospecto-creado'); + $this->dispatch('swal', + icon: 'success', + title: 'Registrado!', + text: 'Se registró el prospecto correctamente', + timer: 2000, + confirm: false, + closeModal: true, + reload: 2000 + ); + $this->resetForm(); } diff --git a/app/Models/Code.php b/app/Models/Code.php new file mode 100644 index 00000000..5aa566ae --- /dev/null +++ b/app/Models/Code.php @@ -0,0 +1,20 @@ + 'datetime', + ]; + + public function user(): BelongsTo + { + return $this->belongsTo(User::class); + } +} diff --git a/app/Models/User.php b/app/Models/User.php index 440c6eb7..33f8a179 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -37,14 +37,11 @@ class User extends Authenticatable 'direccion', 'plantel', 'password', + 'code', 'status', ]; - /** - * The attributes that should be hidden for serialization. - * - * @var array - */ + protected $hidden = [ 'password', 'remember_token', @@ -53,11 +50,7 @@ class User extends Authenticatable 'status', ]; - /** - * The accessors to append to the model's array form. - * - * @var array - */ + protected $appends = [ 'profile_photo_url', ]; @@ -87,6 +80,11 @@ class User extends Authenticatable return $this->hasMany(Note::class); } + public function codes() : HasMany + { + return $this->hasMany(Code::class); + } + public function pagos() : HasMany { return $this->hasMany(Pago::class); diff --git a/app/Providers/FortifyServiceProvider.php b/app/Providers/FortifyServiceProvider.php index 6aa8796e..4a0f42ad 100644 --- a/app/Providers/FortifyServiceProvider.php +++ b/app/Providers/FortifyServiceProvider.php @@ -6,6 +6,7 @@ use App\Actions\Fortify\CreateNewUser; use App\Actions\Fortify\ResetUserPassword; use App\Actions\Fortify\UpdateUserPassword; use App\Actions\Fortify\UpdateUserProfileInformation; +use App\Models\Plantel; use Illuminate\Cache\RateLimiting\Limit; use Illuminate\Http\Request; use Illuminate\Support\Facades\RateLimiter; @@ -38,6 +39,14 @@ class FortifyServiceProvider extends ServiceProvider Fortify::updateUserPasswordsUsing(UpdateUserPassword::class); Fortify::resetUserPasswordsUsing(ResetUserPassword::class); Fortify::redirectUserForTwoFactorAuthenticationUsing(RedirectIfTwoFactorAuthenticatable::class); + Fortify::registerView(function () { + + $plantels = Plantel::where('status',1)->get(); + + return view('auth.register', [ + 'plantels' => $plantels + ]); + }); Fortify::authenticateUsing(function (Request $request) { diff --git a/database/migrations/0001_01_01_000000_create_users_table.php b/database/migrations/0001_01_01_000000_create_users_table.php index f2622a2a..5da5cd45 100644 --- a/database/migrations/0001_01_01_000000_create_users_table.php +++ b/database/migrations/0001_01_01_000000_create_users_table.php @@ -19,6 +19,7 @@ return new class extends Migration $table->unsignedBigInteger('telefono')->unique(); $table->string('direccion'); $table->string('password'); + $table->string('code')->nullable(); $table->boolean('status'); $table->rememberToken(); $table->foreignId('current_team_id')->nullable(); diff --git a/database/migrations/2026_02_05_194540_create_codes_table.php b/database/migrations/2026_02_05_194540_create_codes_table.php new file mode 100644 index 00000000..2815df23 --- /dev/null +++ b/database/migrations/2026_02_05_194540_create_codes_table.php @@ -0,0 +1,31 @@ +id(); + $table->unsignedBigInteger('user_id'); + $table->dateTime('registro')->nullable(); + $table->string('latitud'); + $table->string('longitud'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('codes'); + } +}; diff --git a/database/migrations/2026_02_11_165653_create_area_code_table.php b/database/migrations/2026_02_11_165653_create_area_code_table.php new file mode 100644 index 00000000..879f6fd1 --- /dev/null +++ b/database/migrations/2026_02_11_165653_create_area_code_table.php @@ -0,0 +1,28 @@ +id(); + $table->string('name'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('area_code'); + } +}; diff --git a/database/seeders/AreaCodeSeeder.php b/database/seeders/AreaCodeSeeder.php new file mode 100644 index 00000000..0b3f93ec --- /dev/null +++ b/database/seeders/AreaCodeSeeder.php @@ -0,0 +1,33 @@ +insert([ + 'name' => 'COR-DSIS' + ]); + + DB::table('area_code')->insert([ + 'name' => 'COR-PROG' + ]); + + DB::table('area_code')->insert([ + 'name' => 'COR-CSIS' + ]); + + DB::table('area_code')->insert([ + 'name' => 'COR-RECU' + ]); + + DB::table('area_code')->insert([ + 'name' => 'COR-COMP' + ]); + } +} diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index b563ee2e..9df21622 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -17,6 +17,7 @@ class DatabaseSeeder extends Seeder { $this->call(RoleSeeder::class); $this->call(PlantelSeeder::class); + $this->call(AreaCodeSeeder::class); $this->call(UserSeeder::class); $this->call(NivelSeeder::class); $this->call(DurationSeeder::class); diff --git a/database/seeders/RoleSeeder.php b/database/seeders/RoleSeeder.php index 6e3ad7cd..5a89a1f3 100644 --- a/database/seeders/RoleSeeder.php +++ b/database/seeders/RoleSeeder.php @@ -2,7 +2,6 @@ namespace Database\Seeders; -use Illuminate\Database\Console\Seeds\WithoutModelEvents; use Illuminate\Database\Seeder; use Spatie\Permission\Models\Role; use Spatie\Permission\Models\Permission; @@ -103,5 +102,14 @@ class RoleSeeder extends Seeder Permission::create(['name'=>'concepto.create','description'=>'Crear conceptos'])->syncRoles([$role1]); Permission::create(['name'=>'concepto.edit','description'=>'Editar conceptos'])->syncRoles([$role1]); Permission::create(['name'=>'concepto.destroy','description'=>'Eliminar conceptos'])->syncRoles([$role1]); + + Permission::create(['name'=>'code.index','description'=>'Ver asistencia digital'])->syncRoles([$role1]); + Permission::create(['name'=>'code.create','description'=>'Asistencia digital'])->syncRoles([$role1]); + + Permission::create(['name'=>'asistencia.index','description'=>'Ver asistencias'])->syncRoles([$role1]); + Permission::create(['name'=>'asistencia.create','description'=>'Crear asistencias'])->syncRoles([$role1]); + Permission::create(['name'=>'asistencia.edit','description'=>'Editar asistencias'])->syncRoles([$role1]); + Permission::create(['name'=>'asistencia.destroy','description'=>'Eliminar asistencias'])->syncRoles([$role1]); + } } diff --git a/database/seeders/UserSeeder.php b/database/seeders/UserSeeder.php index 53ecaf90..24156e66 100644 --- a/database/seeders/UserSeeder.php +++ b/database/seeders/UserSeeder.php @@ -19,6 +19,7 @@ class UserSeeder extends Seeder 'direccion'=>'Zacatenco mz 21 lt 2 san francisco cuautliquixca', 'telefono'=>'5636287759', 'password' => bcrypt('6686'), + 'code'=>1, 'status'=>1 ])->assignRole('Admin'); diff --git a/database/seeders/prospectoStatusSeeder.php b/database/seeders/prospectoStatusSeeder.php index d3da65ef..b8dca4b8 100644 --- a/database/seeders/prospectoStatusSeeder.php +++ b/database/seeders/prospectoStatusSeeder.php @@ -4,13 +4,10 @@ namespace Database\Seeders; use Illuminate\Database\Seeder; use Illuminate\Support\Facades\DB; -use Illuminate\Database\Console\Seeds\WithoutModelEvents; class prospectoStatusSeeder extends Seeder { - /** - * Run the database seeds. - */ + public function run(): void { DB::table('prospecto_status')->insert([ diff --git a/resources/views/auth/register.blade.php b/resources/views/auth/register.blade.php index 603a9e00..f33aca65 100644 --- a/resources/views/auth/register.blade.php +++ b/resources/views/auth/register.blade.php @@ -32,6 +32,15 @@
@csrf +
+ + +
@@ -45,7 +54,7 @@
- +
@@ -55,7 +64,7 @@
- +
@@ -84,6 +93,15 @@ @include('layouts._partials.scripts') @livewireScripts @yield('scripts') +@if ($errors->any()) + +@endif diff --git a/resources/views/code/index.blade.php b/resources/views/code/index.blade.php new file mode 100644 index 00000000..61a61cda --- /dev/null +++ b/resources/views/code/index.blade.php @@ -0,0 +1,23 @@ +@extends('layouts.landing') + +@section('title',"Inicio") + +@section('content') + +
+
+
+
Asistencia
+
+ +
+ @livewire('code-scanner') +
+
+
+ +@endsection + +@section('scripts') + +@endsection diff --git a/resources/views/layouts/_partials/code.blade.php b/resources/views/layouts/_partials/code.blade.php new file mode 100644 index 00000000..e5d57a61 --- /dev/null +++ b/resources/views/layouts/_partials/code.blade.php @@ -0,0 +1,3 @@ + diff --git a/resources/views/layouts/_partials/menu.blade.php b/resources/views/layouts/_partials/menu.blade.php index fb7270e1..6d832e91 100644 --- a/resources/views/layouts/_partials/menu.blade.php +++ b/resources/views/layouts/_partials/menu.blade.php @@ -24,14 +24,8 @@ - - - - - - @hasrole('Admin') - --}} - - - {{-- --}} - @hasrole('Promotor') @endrole @@ -167,90 +126,38 @@ @endrole - {{-- --}} - - - - - - - - + --}} - - +
+ + @endcan - - - - - - - - - - - - - - @can('note.index') diff --git a/resources/views/layouts/landing.blade.php b/resources/views/layouts/landing.blade.php index 2ce1d33e..bd85e294 100644 --- a/resources/views/layouts/landing.blade.php +++ b/resources/views/layouts/landing.blade.php @@ -33,30 +33,59 @@ {{-- scripts por vista --}} @yield('scripts') +@stack('scripts') - + diff --git a/resources/views/livewire/code-scanner.blade.php b/resources/views/livewire/code-scanner.blade.php new file mode 100644 index 00000000..031aecac --- /dev/null +++ b/resources/views/livewire/code-scanner.blade.php @@ -0,0 +1,103 @@ +
+
+
+ +

Latitud: Esperando GPS...

+

Longitud: Esperando GPS...

+
+
+ +@push('scripts') + + + + + + +@endpush diff --git a/resources/views/prospecto/index.blade.php b/resources/views/prospecto/index.blade.php index 95a478f6..6369495c 100644 --- a/resources/views/prospecto/index.blade.php +++ b/resources/views/prospecto/index.blade.php @@ -71,35 +71,6 @@ @include('layouts._partials.delete')