From fa8bea206007cc3363c97dac98cad8501d4b0957 Mon Sep 17 00:00:00 2001 From: Juan Felipe Zapata Moreno Date: Mon, 12 Jan 2026 14:49:50 -0600 Subject: [PATCH] =?UTF-8?q?add:=20implementar=20controlador=20y=20modelo?= =?UTF-8?q?=20para=20la=20gesti=C3=B3n=20de=20clientes,=20incluyendo=20rut?= =?UTF-8?q?as=20API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Http/Controllers/App/ClientController.php | 114 ++++++++++++++++++ app/Models/Client.php | 14 +++ ...2026_01_12_131012_create_clients_table.php | 32 +++++ database/seeders/RoleSeeder.php | 92 +++++++++++++- database/seeders/UserSeeder.php | 32 ++--- routes/api.php | 4 + 6 files changed, 266 insertions(+), 22 deletions(-) create mode 100644 app/Http/Controllers/App/ClientController.php create mode 100644 app/Models/Client.php create mode 100644 database/migrations/2026_01_12_131012_create_clients_table.php diff --git a/app/Http/Controllers/App/ClientController.php b/app/Http/Controllers/App/ClientController.php new file mode 100644 index 0000000..62da4f0 --- /dev/null +++ b/app/Http/Controllers/App/ClientController.php @@ -0,0 +1,114 @@ +q}%") + ->orderBy('name') + ->paginate(config('app.pagination')); + + return ApiResponse::OK->response(['clients' => $clients]); + } + + public function show(Client $client) + { + return ApiResponse::OK->response([ + 'client' => $client + ]); + } + + public function store(Request $request) + { + $request->validate([ + 'name' => 'nullable|string|max:255', + 'email' => 'nullable|email|max:255', + 'phone' => 'nullable|string|max:20', + 'address' => 'nullable|string|max:500', + 'rfc' => 'nullable|string|max:13', + ],[ + 'email.unique' => 'El correo electrónico ya está en uso por otro cliente.', + 'phone.unique' => 'El teléfono ya está en uso por otro cliente.', + 'rfc.unique' => 'El RFC ya está en uso por otro cliente.', + ]); + + try{ + + $client = Client::create($request->only([ + 'name', + 'email', + 'phone', + 'address', + 'rfc', + ])); + + return ApiResponse::OK->response([ + 'client' => $client, + 'message' => 'Cliente creado correctamente.' + ]); + + }catch(\Exception $e){ + return ApiResponse::BAD_REQUEST->response([ + 'message' => 'Error al crear el cliente.' + ]); + } + } + + public function update(Request $request, Client $client) + { + $request->validate([ + 'name' => 'nullable|string|max:255', + 'email' => 'nullable|email|max:255', + 'phone' => 'nullable|string|max:20', + 'address' => 'nullable|string|max:500', + 'rfc' => 'nullable|string|max:13', + ],[ + 'email.unique' => 'El correo electrónico ya está en uso por otro cliente.', + 'phone.unique' => 'El teléfono ya está en uso por otro cliente.', + 'rfc.unique' => 'El RFC ya está en uso por otro cliente.', + ]); + + try{ + + $client->update($request->only([ + 'name', + 'email', + 'phone', + 'address', + 'rfc', + ])); + + return ApiResponse::OK->response([ + 'client' => $client, + 'message' => 'Cliente actualizado correctamente.' + ]); + + }catch(\Exception $e){ + return ApiResponse::BAD_REQUEST->response([ + 'message' => 'Error al actualizar el cliente.' + ]); + } + } + + public function destroy(Client $client) + { + try{ + $client->delete(); + + return ApiResponse::OK->response([ + 'message' => 'Cliente eliminado correctamente.' + ]); + + }catch(\Exception $e){ + return ApiResponse::BAD_REQUEST->response([ + 'message' => 'Error al eliminar el cliente.' + ]); + } + } +} diff --git a/app/Models/Client.php b/app/Models/Client.php new file mode 100644 index 0000000..7651a07 --- /dev/null +++ b/app/Models/Client.php @@ -0,0 +1,14 @@ +id(); + $table->string('name'); + $table->string('email')->nullable(); + $table->string('phone')->nullable(); + $table->string('address')->nullable(); + $table->string('rfc')->unique()->nullable(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('clients'); + } +}; diff --git a/database/seeders/RoleSeeder.php b/database/seeders/RoleSeeder.php index f33d004..d7e0a22 100644 --- a/database/seeders/RoleSeeder.php +++ b/database/seeders/RoleSeeder.php @@ -1,4 +1,7 @@ - - * + * * @version 1.0.0 */ class RoleSeeder extends Seeder @@ -61,11 +64,54 @@ public function run(): void ]); $activityIndex = $this->onIndex( - code: 'activities', - type: $pulse, + code: 'activities', + type: $pulse, guardName: 'api' ); + // ==================== NUEVOS PERMISOS PARA PDV ==================== + + // Permisos de Caja + $cashRegisterType = PermissionType::create([ + 'name' => 'Caja registradora' + ]); + + $cashRegisterIndex = $this->onIndex('cash-registers', 'Mostrar datos', $cashRegisterType, 'api'); + $cashRegisterOpen = $this->onPermission('cash-registers.open', 'Abrir caja', $cashRegisterType, 'api'); + $cashRegisterClose = $this->onPermission('cash-registers.close', 'Cerrar caja', $cashRegisterType, 'api'); + $cashRegisterCurrent = $this->onPermission('cash-registers.current', 'Ver caja actual', $cashRegisterType, 'api'); + + // Permisos de Ventas + $salesType = PermissionType::create([ + 'name' => 'Ventas' + ]); + + $salesIndex = $this->onIndex('sales', 'Mostrar datos', $salesType, 'api'); + $salesCreate = $this->onCreate('sales', 'Crear registros', $salesType, 'api'); + $salesCancel = $this->onPermission('sales.cancel', 'Cancelar venta', $salesType, 'api'); + + // Permisos de Inventario (solo lectura) + $inventoryType = PermissionType::create([ + 'name' => 'Inventario' + ]); + + $inventoryIndex = $this->onIndex('inventario', 'Mostrar datos', $inventoryType, 'api'); + + // Permisos de Clientes + $clientsType = PermissionType::create([ + 'name' => 'Clientes' + ]); + + [ + $clientIndex, + $clientCreate, + $clientEdit, + $clientDestroy + ] = $this->onCRUD('clients', $clientsType, 'api'); + + + // ==================== ROLES ==================== + // Desarrollador Role::create([ 'name' => 'developer', @@ -90,7 +136,41 @@ public function run(): void $roleEdit, $roleDestroy, $systemPulse, - $activityIndex + $activityIndex, + // Permisos completos de PDV + $cashRegisterIndex, + $cashRegisterOpen, + $cashRegisterClose, + $cashRegisterCurrent, + $salesIndex, + $salesCreate, + $salesCancel, + $inventoryIndex, + $clientIndex, + $clientCreate, + $clientEdit, + $clientDestroy + ); + + //Operador PDV (solo permisos de operación de caja y ventas) + Role::create([ + 'name' => 'operador_pdv', + 'description' => 'Operador de Punto de Venta', + 'guard_name' => 'api' + ])->givePermissionTo( + // Caja + $cashRegisterIndex, // Ver historial de cajas + $cashRegisterOpen, // Abrir caja + $cashRegisterClose, // Cerrar caja + $cashRegisterCurrent, // Ver caja actual + // Ventas + $salesIndex, // Ver historial de ventas + $salesCreate, // Crear ventas + // Inventario (solo lectura) + $inventoryIndex, // Listar productos + // Clientes + $clientIndex, // Buscar clientes + $clientCreate // Crear clientes ); } } diff --git a/database/seeders/UserSeeder.php b/database/seeders/UserSeeder.php index d6716c5..e9221be 100644 --- a/database/seeders/UserSeeder.php +++ b/database/seeders/UserSeeder.php @@ -9,9 +9,9 @@ /** * Usuarios predeterminados del sistema - * + * * @author Moisés Cortés C. - * + * * @version 1.0.0 */ class UserSeeder extends Seeder @@ -21,34 +21,34 @@ class UserSeeder extends Seeder */ public function run(): void { - $developer = UserSecureSupport::create('developer@notsoweb.com'); + $developer = UserSecureSupport::create('developer@golsystems.com'); User::create([ 'name' => 'Developer', - 'paternal' => 'Notsoweb', - 'maternal' => 'Software', + 'paternal' => 'Golsystems', + 'maternal' => 'Dev', 'email' => $developer->email, 'password' => $developer->hash, ])->assignRole(__('developer')); - $admin = UserSecureSupport::create('admin@notsoweb.com'); + $admin = UserSecureSupport::create('admin@golsystems.com'); User::create([ 'name' => 'Admin', - 'paternal' => 'Notsoweb', - 'maternal' => 'Software', + 'paternal' => 'Golsystems', + 'maternal' => 'Dev', 'email' => $admin->email, - 'password' => $admin->hash, + 'password' => 'SoyAdmin123..', ])->assignRole(__('admin')); - $demo = UserSecureSupport::create('demo@notsoweb.com'); + $operadorPdv = UserSecureSupport::create('opv@golsystems.com'); User::create([ - 'name' => 'Demo', - 'paternal' => 'Notsoweb', - 'maternal' => 'Software', - 'email' => $demo->email, - 'password' => $demo->hash, - ]); + 'name' => 'Operador PDV', + 'paternal' => 'Golsystems', + 'maternal' => 'Dev', + 'email' => $operadorPdv->email, + 'password' => $operadorPdv->hash, + ])->assignRole(__('operador_pdv')); } } diff --git a/routes/api.php b/routes/api.php index d34174b..04193aa 100644 --- a/routes/api.php +++ b/routes/api.php @@ -2,6 +2,7 @@ use App\Http\Controllers\App\CashRegisterController; use App\Http\Controllers\App\CategoryController; +use App\Http\Controllers\App\ClientController; use App\Http\Controllers\App\InventoryController; use App\Http\Controllers\App\PriceController; use App\Http\Controllers\App\ReportController; @@ -55,6 +56,9 @@ Route::get('top-selling-product', [ReportController::class, 'topSellingProduct']); Route::get('products-without-movement', [ReportController::class, 'productsWithoutMovement']); }); + + //CLIENTES + Route::resource('clients', ClientController::class); }); /** Rutas públicas */