diff --git a/README.md b/README.md index 75c347a..6880eba 100644 --- a/README.md +++ b/README.md @@ -1,61 +1,1104 @@ -

Laravel Logo

+# 🚴 Sistema de Gestión Lauck -

-Build Status -Total Downloads -Latest Stable Version -License -

+**Sistema web integral para gestión de bicicletería** - Inventario, ventas, taller, clientes y catálogo público. -## About Laravel +[![Laravel](https://img.shields.io/badge/Laravel-12-red.svg)](https://laravel.com) +[![PHP](https://img.shields.io/badge/PHP-8.2+-blue.svg)](https://php.net) +[![Tailwind CSS](https://img.shields.io/badge/Tailwind_CSS-4.0-38bdf8.svg)](https://tailwindcss.com) +[![License](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE) -Laravel is a web application framework with expressive, elegant syntax. We believe development must be an enjoyable and creative experience to be truly fulfilling. Laravel takes the pain out of development by easing common tasks used in many web projects, such as: +## 📋 Descripción -- [Simple, fast routing engine](https://laravel.com/docs/routing). -- [Powerful dependency injection container](https://laravel.com/docs/container). -- Multiple back-ends for [session](https://laravel.com/docs/session) and [cache](https://laravel.com/docs/cache) storage. -- Expressive, intuitive [database ORM](https://laravel.com/docs/eloquent). -- Database agnostic [schema migrations](https://laravel.com/docs/migrations). -- [Robust background job processing](https://laravel.com/docs/queues). -- [Real-time event broadcasting](https://laravel.com/docs/broadcasting). +**Lauck** es un sistema de gestión completo diseñado específicamente para bicicleterías. Integra la gestión de inventario, ventas, taller mecánico, base de datos de clientes y un catálogo público para visitantes, todo en una única plataforma web moderna y responsiva. -Laravel is accessible, powerful, and provides tools required for large, robust applications. +## ✨ Características Principales -## Learning Laravel +### 🔐 Sistema de Autenticación y Roles +- **Registro de usuarios** con validación completa +- **Login seguro** con rate limiting (5 intentos/minuto) +- **Gestión de sesiones** en base de datos +- **Sistema de roles**: Admin, Empleado, Invitado +- **Protección de rutas** con middleware +- **Dashboard personalizado** según permisos -Laravel has the most extensive and thorough [documentation](https://laravel.com/docs) and video tutorial library of all modern web application frameworks, making it a breeze to get started with the framework. +### 📦 Gestión Avanzada de Productos +#### Atributos del Producto: +- Nombre, SKU (generación automática) +- Tipo: Bicicleta, Accesorio, Indumentaria, Repuesto +- Precio de venta y costo (solo admin) +- Stock actual y alerta de stock mínimo +- Descripción detallada +- **Número de serie** (para bicicletas) +- **Imágenes** con upload y visualización -You may also try the [Laravel Bootcamp](https://bootcamp.laravel.com), where you will be guided through building a modern Laravel application from scratch. +#### Funcionalidades: +- ✅ **CRUD completo** (Crear, Leer, Actualizar, Eliminar) +- 🔍 **Buscador avanzado** (nombre, SKU) +- 🎨 **Filtros dinámicos** por estado de stock (Alerta, Bajo, Normal) +- 📊 **Indicadores visuales** de stock con colores (rojo/amarillo/verde) +- 🖼️ **Gestión de imágenes** con upload y storage +- 📄 **Paginación** optimizada (10 productos/página) +- 🏷️ **Badges de tipo** con diseño diferenciado -If you don't feel like reading, [Laracasts](https://laracasts.com) can help. Laracasts contains thousands of video tutorials on a range of topics including Laravel, modern PHP, unit testing, and JavaScript. Boost your skills by digging into our comprehensive video library. +### 💰 Sistema de Ventas (POS) +#### Características del Punto de Venta: +- **Interfaz intuitiva** estilo POS moderno +- **Selector de productos** con Select2 y búsqueda en tiempo real +- **Bloqueo de productos duplicados** en el mismo ticket +- **Cálculo automático** de subtotales y total +- **Gestión de clientes**: Asociar venta a cliente o "Consumidor Final" +- **Métodos de pago**: Efectivo, Débito, Crédito, Transferencia +- **Agregar/quitar productos** dinámicamente +- **Contador de items** en tiempo real -## Laravel Sponsors +#### Procesamiento de Ventas: +- ✅ **Transacciones atómicas** (rollback automático en caso de error) +- 📉 **Descuento automático de stock** al confirmar venta +- 💾 **Registro de detalles** (SaleDetails) por cada producto vendido +- 🧾 **Comprobante imprimible** en formato ticket profesional +- 📊 **Historial de ventas** con paginación -We would like to extend our thanks to the following sponsors for funding Laravel development. If you are interested in becoming a sponsor, please visit the [Laravel Partners program](https://partners.laravel.com). +#### Comprobante de Venta: +- Diseño profesional tipo factura +- Header con logo y datos del negocio +- Información del cliente (o "Consumidor Final") +- Tabla detallada de productos +- Método de pago destacado +- Total en tamaño grande +- **Botón de impresión/PDF** optimizado +- Estilos específicos para impresión -### Premium Partners +### 👥 Gestión de Clientes +- **Base de datos completa** de clientes ciclistas +- Campos: Nombre, Teléfono/WhatsApp, Email, Dirección +- **CRUD completo** de clientes +- **Búsqueda** por nombre, teléfono o email +- **Paginación** de resultados +- **Protección contra eliminación** si tiene ventas registradas +- **Integración con ventas**: Seleccionar cliente en POS +- **Creación rápida** desde POS con redirección automática -- **[Vehikl](https://vehikl.com)** -- **[Tighten Co.](https://tighten.co)** -- **[Kirschbaum Development Group](https://kirschbaumdevelopment.com)** -- **[64 Robots](https://64robots.com)** -- **[Curotec](https://www.curotec.com/services/technologies/laravel)** -- **[DevSquad](https://devsquad.com/hire-laravel-developers)** -- **[Redberry](https://redberry.international/laravel-development)** -- **[Active Logic](https://activelogic.com)** +### 🔧 Gestión de Taller (Mecánica) +#### Sistema Kanban de Órdenes de Reparación: +- **Tablero visual** estilo Trello con 3 columnas: + - 🔴 **Pendientes** - Bicis recién ingresadas + - 🟡 **En Reparación** - Trabajo en progreso + - 🟢 **Listas para Retirar** - Trabajos finalizados -## Contributing +#### Información de Orden: +- Cliente asociado +- Modelo y color de bicicleta +- Descripción del problema +- **Lista de repuestos necesarios** con precios +- **Presupuesto estimado** (calculado automáticamente) +- Fecha/hora prometida de entrega +- Teléfono de contacto rápido +- Notas del mecánico -Thank you for considering contributing to the Laravel framework! The contribution guide can be found in the [Laravel documentation](https://laravel.com/docs/contributions). +#### Funcionalidades Kanban: +- ✅ **Mover cards** entre estados (flechas) +- ↩️ **Regresar al estado anterior** si es necesario +- 💬 **Botón de WhatsApp** para avisar al cliente +- ✔️ **Marcar como entregado** (archiva la orden) +- 🎨 **Bordes de color** según estado +- 📱 **Scroll independiente** por columna +- 🔢 **Contador de items** por columna -## Code of Conduct +#### Creación de Orden: +- **Selector de cliente** con búsqueda +- **Auto-completar teléfono** al seleccionar cliente +- **Buscador de repuestos** en tiempo real +- **Lista visual** de repuestos seleccionados +- **Cálculo automático** del presupuesto total +- **Validación completa** de datos +- **Botón de crear cliente** sin salir del formulario -In order to ensure that the Laravel community is welcoming to all, please review and abide by the [Code of Conduct](https://laravel.com/docs/contributions#code-of-conduct). +### 🌐 Catálogo Público +#### Vista para Visitantes (sin login): +- **Listado público** de productos en stock +- **Cards atractivos** con imagen, nombre, precio +- **Búsqueda integrada** en navbar +- **Paginación** automática (12 productos/página) +- **Vista de detalle** profesional con: + - Imagen a tamaño completo + - Información completa del producto + - Indicador de stock en tiempo real + - Precio destacado + - Botones de contacto (teléfono, WhatsApp) + - Diseño responsivo premium -## Security Vulnerabilities +#### Carrousel Destacados: +- **Slider automático** de productos destacados +- **Controles manuales** (flechas y puntos) +- **Auto-play** cada 5 segundos +- **Diseño dual**: Imagen + Info +- **Precio flotante** con efecto +- **Navegación fluida** con transiciones -If you discover a security vulnerability within Laravel, please send an e-mail to Taylor Otwell via [taylor@laravel.com](mailto:taylor@laravel.com). All security vulnerabilities will be promptly addressed. +### 🎨 Sistema de Diseño -## License +#### Paleta de Colores Personalizada: +- **Neon Lime** (`#ccff00`): Color principal/acción +- **Dark Background** (`#1a1a1a`): Fondo principal +- **Panel Background** (`#242424`): Paneles/tarjetas +- **Neutral 800/900**: Componentes UI +- **Gradientes**: Efectos visuales modernos -The Laravel framework is open-sourced software licensed under the [MIT license](https://opensource.org/licenses/MIT). +#### Componentes Reutilizables: +``` +components/ +├── layout.blade.php # Layout principal autenticado +├── appc.blade.php # Layout público (visitantes) +├── navbar.blade.php # Navegación contextual +├── footer.blade.php # Pie de página +├── section-header.blade.php # Encabezados de sección +├── taller-card.blade.php # Card de orden de taller +├── ui/ +│ ├── alert.blade.php # Alertas de feedback +│ ├── badge.blade.php # Etiquetas de estado +│ ├── card.blade.php # Tarjetas de dashboard +│ ├── imgcard.blade.php # Card de producto con imagen +│ └── carrousel.blade.php # Carrousel de destacados +└── forms/ + ├── input.blade.php # Input con validación + ├── label.blade.php # Label estandarizado + └── select.blade.php # Select estilizado +``` + +#### Efectos Visuales: +- 🌟 **Patrón de grilla de fondo** con efecto técnico +- 💫 **Hover states** en todos los elementos interactivos +- 🎭 **Transiciones suaves** en navegación +- 📱 **Diseño responsivo** 100% mobile-first +- 🎨 **Scrollbar personalizado** con colores del tema +- ⚡ **Loading indicators** donde corresponde + +## 🏗️ Arquitectura del Sistema + +### Flujo de Navegación Completo + +``` +┌────────────────────────────────────────────────────┐ +│ Landing Page (/) │ +│ - Carrousel de productos destacados │ +│ - Navbar con catálogo público │ +│ - Botón "Ingresar" para staff │ +└─────────────────┬──────────────────────────────────┘ + │ + ┌─────────┴─────────┐ + │ │ + VISITANTE STAFF + │ │ + ▼ ▼ +┌──────────────┐ ┌──────────────┐ +│ Catálogo │ │ Login │ +│ Público │ │ │ +│ /catalogo │ │ /login │ +└──────────────┘ └──────┬───────┘ + │ │ + │ ▼ + │ ┌──────────────┐ + │ │ Dashboard │ + │ │ (autenticado)│ + │ └──────┬───────┘ + │ │ + │ ┌───────────┼───────────┬──────────┐ + │ │ │ │ │ + ▼ ▼ ▼ ▼ ▼ + ┌─────┐ ┌─────┐ ┌──────┐ ┌───────┐ ┌─────┐ + │ Ver │ │Stock│ │Ventas│ │Clientes│ │Taller│ + │Prod.│ │/prod│ │/sales│ │/clients│ │/taller│ + └─────┘ └─────┘ └──────┘ └────────┘ └─────┘ +``` + +### Estructura MVC Detallada + +#### 📁 Modelos (app/Models) +```php +User.php // Usuarios con roles (admin/employee/guest) +Product.php // Productos con relaciones +Client.php // Clientes con validaciones +Sale.php // Ventas (cabecera) +SaleDetail.php // Detalles de venta (renglones) +Appointment.php // Órdenes de taller +Supplier.php // Proveedores (implementación futura) +``` + +#### 🎮 Controladores (app/Http/Controllers) +```php +HomeController.php // Landing page con destacados +LoginController.php // Autenticación +RegisterController.php // Registro de usuarios +ProductosController.php // CRUD de productos +SaleController.php // Sistema de ventas (POS) +ClientController.php // Gestión de clientes +TallerController.php // Gestión de taller (Kanban) +CatalogoController.php // Catálogo público +``` + +#### 👁️ Vistas (resources/views) +``` +views/ +├── welcome.blade.php # Landing page +├── login.blade.php # Inicio de sesión +├── register.blade.php # Registro +├── dashboard.blade.php # Panel principal +├── productos/ +│ ├── index.blade.php # Listado de productos +│ ├── create.blade.php # Crear producto +│ ├── edit.blade.php # Editar producto +│ └── show.blade.php # Ver detalle +├── sales/ +│ ├── index.blade.php # Historial de ventas +│ ├── create.blade.php # POS (punto de venta) +│ └── show.blade.php # Comprobante de venta +├── clients/ +│ ├── index.blade.php # Listado de clientes +│ ├── create.blade.php # Alta de cliente +│ └── edit.blade.php # Modificar cliente +├── taller/ +│ ├── index.blade.php # Tablero Kanban +│ └── create.blade.php # Nueva orden +└── catalogo/ + ├── index.blade.php # Catálogo público + └── show.blade.php # Detalle producto público +``` + +## 🚀 Stack Tecnológico + +### Backend +- **Laravel 12.x** - Framework PHP moderno +- **PHP 8.2+** - Lenguaje de programación +- **SQLite** - Base de datos (configurable a MySQL/PostgreSQL) +- **Eloquent ORM** - Gestión de base de datos +- **Laravel Factories & Seeders** - Datos de prueba + +### Frontend +- **Tailwind CSS 4.0** - Framework CSS utility-first +- **Blade Components** - Sistema de componentes reutilizables +- **jQuery 3.7.1** - Manipulación DOM +- **Select2 4.1** - Selectores avanzados con búsqueda +- **Vite 7.0** - Build tool y HMR +- **Montserrat Font** - Tipografía principal + +### JavaScript/Bibliotecas +```json +{ + "jquery": "^3.7.1", + "select2": "^4.1.0-rc.0", + "axios": "^1.8.2" +} +``` + +### Herramientas de Desarrollo +- **Composer** - Gestor de dependencias PHP +- **NPM** - Gestor de paquetes JavaScript +- **Laravel Pint** - Code styling +- **Laravel Sail** - Entorno Docker (opcional) +- **Concurrently** - Múltiples procesos en desarrollo + +## 📊 Base de Datos + +### Esquema Completo + +#### Tabla: `users` +```sql +id BIGINT PRIMARY KEY +name VARCHAR(255) +email VARCHAR(255) UNIQUE +role ENUM('admin', 'employee', 'guest') +email_verified_at TIMESTAMP NULLABLE +password VARCHAR(255) +remember_token VARCHAR(100) NULLABLE +created_at TIMESTAMP +updated_at TIMESTAMP +``` + +#### Tabla: `products` +```sql +id BIGINT PRIMARY KEY +name VARCHAR(255) +sku VARCHAR(50) UNIQUE NULLABLE +description TEXT NULLABLE +price DECIMAL(10,2) +cost DECIMAL(10,2) NULLABLE +stock_quantity INTEGER DEFAULT 0 +min_stock_alert INTEGER +type ENUM('bike','accessory','clothing','spare') +serial_number VARCHAR(100) NULLABLE +image_path VARCHAR(255) NULLABLE +suppliers_id BIGINT FOREIGN KEY +created_at TIMESTAMP +updated_at TIMESTAMP +``` + +#### Tabla: `clients` +```sql +id BIGINT PRIMARY KEY +name VARCHAR(255) +phone VARCHAR(50) NULLABLE +email VARCHAR(255) NULLABLE UNIQUE +address TEXT NULLABLE +created_at TIMESTAMP +updated_at TIMESTAMP +``` + +#### Tabla: `sales` +```sql +id BIGINT PRIMARY KEY +client_id BIGINT FOREIGN KEY NULLABLE +total DECIMAL(10,2) +payment_method VARCHAR(255) +created_at TIMESTAMP +updated_at TIMESTAMP +``` + +#### Tabla: `sale_details` +```sql +id BIGINT PRIMARY KEY +sale_id BIGINT FOREIGN KEY ON DELETE CASCADE +product_id BIGINT FOREIGN KEY +quantity INTEGER +price DECIMAL(10,2) +created_at TIMESTAMP +updated_at TIMESTAMP +``` + +#### Tabla: `appointments` (Taller) +```sql +id BIGINT PRIMARY KEY +client_id BIGINT FOREIGN KEY ON DELETE CASCADE +contact_phone VARCHAR(50) NULLABLE +scheduled_at DATETIME +bike_model VARCHAR(255) +problem_description TEXT +parts_needed TEXT NULLABLE +estimated_cost DECIMAL(10,2) NULLABLE +status ENUM('pending','in_progress','ready','delivered') +notes TEXT NULLABLE +created_at TIMESTAMP +updated_at TIMESTAMP +``` + +#### Tabla: `suppliers` +```sql +id BIGINT PRIMARY KEY +name VARCHAR(255) +phone VARCHAR(50) +email VARCHAR(255) +created_at TIMESTAMP +updated_at TIMESTAMP +``` + +### Relaciones del Modelo + +``` +User (1) ──────────── (N) Sale +Client (1) ────┬───── (N) Sale + └───── (N) Appointment +Product (1) ──┬─────── (N) SaleDetail + └─────── (1) Supplier +Sale (1) ────────────── (N) SaleDetail +``` + +## 🚀 Instalación + +### Requisitos Previos +```bash +PHP >= 8.2 +Composer >= 2.x +Node.js >= 18.x +NPM >= 9.x +SQLite (o MySQL/PostgreSQL) +``` + +### Instalación Paso a Paso + +```bash +# 1. Clonar el repositorio +git clone https://github.com/tu-usuario/lauck.git +cd lauck + +# 2. Instalar dependencias de PHP +composer install + +# 3. Instalar dependencias de JavaScript +npm install + +# 4. Configurar variables de entorno +cp .env.example .env + +# 5. Generar clave de aplicación +php artisan key:generate + +# 6. Crear base de datos SQLite +touch database/database.sqlite + +# 7. Configurar .env (verificar estas líneas) +DB_CONNECTION=sqlite +DB_DATABASE=/ruta/absoluta/database/database.sqlite + +# 8. Ejecutar migraciones +php artisan migrate + +# 9. Poblar base de datos con datos de prueba +php artisan db:seed + +# 10. Crear enlace simbólico para imágenes +php artisan storage:link + +# 11. Compilar assets para desarrollo +npm run dev +# O para producción: +npm run build + +# 12. Iniciar servidor de desarrollo +php artisan serve +``` + +### Desarrollo Concurrente (Recomendado) + +Laravel incluye un script `dev` en `composer.json` que ejecuta: +```bash +composer run dev +``` + +Esto inicia simultáneamente: +- 🌐 Servidor PHP (puerto 8000) +- 📦 Queue listener +- 📋 Pail (logs en tiempo real) +- ⚡ Vite (HMR) + +### Acceso a la Aplicación + +``` +URL Principal: http://localhost:8000 +Catálogo: http://localhost:8000/catalogo +Admin: http://localhost:8000/dashboard +``` + +### Credenciales de Prueba (Seeder) + +**Administrador:** +- Email: `admin@lauck.com` +- Password: `password` + +**Empleado:** +- Email: `taller@lauck.com` +- Password: `password` + +## 🧪 Datos de Prueba + +El seeder carga automáticamente: +- ✅ 2 usuarios (1 admin, 1 empleado) +- ✅ 1 proveedor genérico +- ✅ 50+ productos variados (bicis, accesorios, repuestos) +- ✅ 1 cliente de ejemplo +- ✅ 1 orden de taller de ejemplo + +```bash +# Limpiar y recargar todo +php artisan migrate:fresh --seed +``` + +## 🎯 Próximas Funcionalidades (Roadmap) + +### Prioridad Alta 🔴 + +#### 1. Sistema de Compras a Proveedores +``` +Features: +- Registrar pedidos a proveedores +- Control de órdenes de compra +- Recepción de mercadería +- Actualización automática de stock +- Historial de compras por proveedor +``` + +#### 2. Reportes y Estadísticas +``` +Dashboard mejorado con: +- Ventas del día/mes/año (gráficos) +- Productos más vendidos +- Stock crítico (alertas) +- Rendimiento por categoría +- Clientes frecuentes +- Exportación a PDF/Excel +``` + +#### 3. Sistema de Usuarios Completo +``` +- Gestión de empleados +- Permisos granulares por módulo +- Registro de actividad (logs) +- Auditoría de cambios +``` + +#### 4. Mejoras en el POS +``` +- Descuentos por producto/venta +- Venta a crédito / financiación +- Múltiples formas de pago en una venta +- Impresión directa de tickets +- Devoluciones y notas de crédito +``` + +### Prioridad Media 🟡 + +#### 5. Notificaciones Automáticas +``` +- Email de comprobante de venta +- WhatsApp API para avisos de taller +- Recordatorios de retiro +- Alertas de stock bajo +``` + +#### 6. Historial de Taller Completo +``` +- Archivo de trabajos entregados +- Búsqueda de histórico por cliente +- Estadísticas de reparaciones +- Reputación del mecánico +``` + +#### 7. Catálogo Mejorado +``` +- Sistema de categorías jerárquicas +- Comparador de productos +- Favoritos/Wishlist +- Reseñas de clientes +- Galería de múltiples imágenes +``` + +#### 8. Integración con MercadoPago/Stripe +``` +- Pagos online para catálogo +- Reservas con seña +- Panel de conciliación +``` + +### Prioridad Baja 🟢 + +#### 9. App Móvil (PWA) +``` +- Instalable como app +- Notificaciones push +- Modo offline básico +``` + +#### 10. Integraciones +``` +- Sincronización con contabilidad +- API pública RESTful +- Webhooks para eventos +- Importación masiva (Excel/CSV) +``` + +#### 11. Marketing +``` +- Email marketing a clientes +- Campañas promocionales +- Cupones de descuento +- Programa de puntos/fidelidad +``` + +#### 12. Multi-sucursal +``` +- Gestión de múltiples locales +- Transferencias entre sucursales +- Stock por local +- Reportes consolidados +``` + +## 🔧 Mejoras Técnicas Recomendadas + +### Optimización de Rendimiento + +#### 1. Implementar Caché Estratégico +```php +// ProductosController.php +public function index(Request $request) +{ + $cacheKey = 'products.' . md5(serialize($request->all())); + + $products = Cache::remember($cacheKey, 300, function () use ($request) { + return Product::query() + ->when($request->search, fn($q, $term) => + $q->where('name', 'like', "%{$term}%") + ) + ->paginate(10); + }); +} + +// Limpiar caché al modificar productos +Cache::forget('products.*'); +``` + +#### 2. Eager Loading para Relaciones +```php +// Evitar N+1 queries +$sales = Sale::with(['client', 'details.product']) + ->latest() + ->paginate(15); + +// En lugar de: +$sales = Sale::all(); // Genera queries adicionales +``` + +#### 3. Índices de Base de Datos +```php +// En migraciones +Schema::table('products', function (Blueprint $table) { + $table->index('sku'); + $table->index('type'); + $table->index(['stock_quantity', 'min_stock_alert']); +}); + +Schema::table('sales', function (Blueprint $table) { + $table->index('created_at'); + $table->index(['client_id', 'created_at']); +}); +``` + +#### 4. Paginación con Cursor +```php +// Para datasets grandes +$products = Product::latest()->cursorPaginate(20); +``` + +### Refactorización de Código + +#### 1. Services para Lógica de Negocio +```php +// app/Services/SaleService.php +class SaleService +{ + public function processSale(array $data): Sale + { + return DB::transaction(function () use ($data) { + $sale = Sale::create([...]); + + foreach ($data['items'] as $item) { + $this->addItem($sale, $item); + } + + return $sale; + }); + } + + private function addItem(Sale $sale, array $item): void + { + $product = Product::findOrFail($item['product_id']); + + if ($product->stock_quantity < $item['quantity']) { + throw new InsufficientStockException(); + } + + SaleDetail::create([...]); + $product->decrement('stock_quantity', $item['quantity']); + } +} +``` + +#### 2. Form Request Validation +```php +// app/Http/Requests/StoreSaleRequest.php +class StoreSaleRequest extends FormRequest +{ + public function rules(): array + { + return [ + 'client_id' => 'nullable|exists:clients,id', + 'payment_method' => 'required|string', + 'items' => 'required|array|min:1', + 'items.*.product_id' => 'required|exists:products,id', + 'items.*.quantity' => 'required|integer|min:1', + ]; + } + + public function messages(): array + { + return [ + 'items.required' => 'Debe agregar al menos un producto.', + 'items.*.quantity.min' => 'La cantidad debe ser mayor a 0.', + ]; + } +} + +// En el controlador +public function store(StoreSaleRequest $request) +{ + // $request ya está validado +} +``` + +#### 3. Repository Pattern +```php +// app/Repositories/ProductRepository.php +interface ProductRepositoryInterface +{ + public function search(string $term): Collection; + public function lowStock(): Collection; + public function byType(string $type): Collection; +} + +class ProductRepository implements ProductRepositoryInterface +{ + public function search(string $term): Collection + { + return Product::where('name', 'like', "%{$term}%") + ->orWhere('sku', 'like', "%{$term}%") + ->get(); + } +} + +// Registrar en AppServiceProvider +$this->app->bind( + ProductRepositoryInterface::class, + ProductRepository::class +); +``` + +#### 4. Policies para Autorización +```php +// app/Policies/ProductPolicy.php +class ProductPolicy +{ + public function viewAny(User $user): bool + { + return in_array($user->role, ['admin', 'employee']); + } + + public function create(User $user): bool + { + return $user->role === 'admin'; + } + + public function update(User $user, Product $product): bool + { + return $user->role === 'admin'; + } + + public function delete(User $user, Product $product): bool + { + return $user->role === 'admin'; + } +} + +// En controlador +$this->authorize('create', Product::class); +``` + +### Mejoras de Seguridad + +#### 1. Rate Limiting Específico +```php +// routes/web.php +Route::post('/sales', [SaleController::class, 'store']) + ->middleware(['auth', 'throttle:sales']); + +// app/Providers/RouteServiceProvider.php +RateLimiter::for('sales', function (Request $request) { + return Limit::perMinute(10)->by($request->user()?->id); +}); +``` + +#### 2. Sanitización de Inputs +```php +// En Form Request +protected function prepareForValidation() +{ + $this->merge([ + 'name' => strip_tags($this->name), + 'description' => Purifier::clean($this->description), + ]); +} +``` + +#### 3. Protección CSRF Explícita +```php +// Verificar en AJAX +$.ajaxSetup({ + headers: { + 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') + } +}); +``` + +#### 4. Validación de Imágenes +```php +'image' => [ + 'nullable', + 'image', + 'mimes:jpeg,png,jpg,webp', + 'max:2048', // 2MB + 'dimensions:min_width=100,min_height=100,max_width=2000,max_height=2000' +] +``` + +### Mejoras de UI/UX + +#### 1. Loading States +```blade + + + +``` + +#### 2. Confirmaciones Elegantes +```javascript +// Usar SweetAlert2 +Swal.fire({ + title: '¿Eliminar producto?', + text: "Esta acción no se puede revertir", + icon: 'warning', + showCancelButton: true, + confirmButtonColor: '#ccff00', + cancelButtonColor: '#d33', + confirmButtonText: 'Sí, eliminar', + cancelButtonText: 'Cancelar' +}).then((result) => { + if (result.isConfirmed) { + // Ejecutar eliminación + } +}); +``` + +#### 3. Toast Notifications +```javascript +// Mensajes no intrusivos +const Toast = Swal.mixin({ + toast: true, + position: 'top-end', + showConfirmButton: false, + timer: 3000 +}); + +Toast.fire({ + icon: 'success', + title: 'Producto guardado' +}); +``` + +#### 4. Validación en Tiempo Real +```javascript +$('input[name="sku"]').on('blur', function() { + const sku = $(this).val(); + + $.get(`/api/products/check-sku/${sku}`, function(data) { + if (data.exists) { + // Mostrar error + $(this).addClass('border-red-500'); + } + }); +}); +``` + +### Testing + +#### 1. Tests de Feature +```php +// tests/Feature/ProductTest.php +public function test_admin_can_create_product() +{ + $admin = User::factory()->create(['role' => 'admin']); + + $this->actingAs($admin) + ->post('/productos', [ + 'name' => 'Test Product', + 'price' => 100, + 'stock_quantity' => 10, + 'min_stock_alert' => 5, + 'type' => 'accessory' + ]) + ->assertRedirect('/productos') + ->assertSessionHas('success'); + + $this->assertDatabaseHas('products', [ + 'name' => 'Test Product' + ]); +} + +public function test_guest_cannot_create_product() +{ + $response = $this->post('/productos', []); + $response->assertRedirect('/login'); +} +``` + +#### 2. Tests Unitarios +```php +// tests/Unit/ProductTest.php +public function test_product_has_low_stock() +{ + $product = Product::factory()->create([ + 'stock_quantity' => 3, + 'min_stock_alert' => 5 + ]); + + $this->assertTrue($product->hasLowStock()); +} +``` + +#### 3. Browser Tests (Dusk) +```php +// tests/Browser/PosTest.php +public function test_can_complete_sale() +{ + $this->browse(function (Browser $browser) { + $browser->loginAs(User::find(1)) + ->visit('/sales/create') + ->select('items[0][product_id]', 1) + ->type('items[0][quantity]', 2) + ->press('Confirmar Venta') + ->assertPathIs('/sales/1'); + }); +} +``` + +## 🐛 Issues Conocidos y Soluciones + +### 1. Select2 no se inicializa en filas dinámicas +**Problema**: Al agregar nueva fila en POS, Select2 no funciona. + +**Solución actual**: +```javascript +$('.select2-product').select2('destroy'); // Destruir +const newRow = firstRow.clone(); // Clonar +initSelect2(); // Re-inicializar todos +``` + +**Mejora sugerida**: +```javascript +function addRow() { + const newRow = firstRow.clone(); + container.append(newRow); + newRow.find('.select2-product').select2({ /* config */ }); +} +``` + +### 2. Imágenes no se muestran después de upload +**Problema**: Falta ejecutar `storage:link`. + +**Solución**: +```bash +php artisan storage:link +``` + +### 3. Error en eliminación de cliente con ventas +**Problema**: Violación de constraint de foreign key. + +**Solución implementada**: Try-catch con mensaje amigable. + +**Mejora**: Soft deletes +```php +// En migración +$table->softDeletes(); + +// En modelo +use SoftDeletes; +``` + +### 4. Problema de concurrencia en stock +**Escenario**: Dos ventas simultáneas del mismo producto. + +**Solución recomendada**: Optimistic locking +```php +// En modelo Product +protected $casts = [ + 'version' => 'integer' +]; + +// Al actualizar +Product::where('id', $id) + ->where('version', $currentVersion) + ->update([ + 'stock_quantity' => $newStock, + 'version' => $currentVersion + 1 + ]); +``` + +## 📝 Convenciones y Estándares + +### Nombres +- **Variables**: `camelCase` (`$productoActual`) +- **Funciones**: `camelCase` (`getUserData()`) +- **Clases**: `PascalCase` (`ProductController`) +- **Tablas**: `snake_case` plural (`products`, `sale_details`) +- **Rutas**: `kebab-case` (`/productos/crear`) + +### Commits +``` +Add: Nueva funcionalidad +Fix: Corrección de bugs +Update: Actualización de código existente +Refactor: Refactorización sin cambios funcionales +Docs: Cambios en documentación +Style: Formato/estilo (sin cambios lógicos) +Test: Agregar/modificar tests +Chore: Tareas de mantenimiento +``` + +### Branches +``` +main/master - Producción +develop - Desarrollo +feature/nombre - Nueva funcionalidad +fix/nombre - Corrección de bugs +hotfix/nombre - Corrección urgente en producción +``` + +## 🤝 Contribuir + +### Proceso +1. Fork del proyecto +2. Crear rama: `git checkout -b feature/AmazingFeature` +3. Commit: `git commit -m 'Add: nueva funcionalidad'` +4. Push: `git push origin feature/AmazingFeature` +5. Abrir Pull Request + +### Checklist antes del PR +- [ ] Código sigue las convenciones +- [ ] Tests pasan (`php artisan test`) +- [ ] No hay errores de linting (`composer run lint`) +- [ ] Documentación actualizada +- [ ] Migraciones incluidas si aplica +- [ ] Seeders actualizados si aplica + +## 📄 Licencia + +Este proyecto está bajo la Licencia MIT. Ver archivo `LICENSE` para detalles. + +## 🙏 Agradecimientos + +- [Laravel](https://laravel.com) - El framework PHP para artesanos web +- [Tailwind CSS](https://tailwindcss.com) - Framework CSS utility-first +- [Select2](https://select2.org) - Selectores avanzados +- [jQuery](https://jquery.com) - Manipulación DOM simplificada +- Comunidad de Laravel por su excelente documentación + +## 📞 Contacto + +**Bicicletería Lauck** +- Dirección: Av. Francisco Ramírez 1389, Paraná, Entre Ríos +- Teléfono: 343 422-0103 +- Web: En desarrollo + +--- + +**Versión**: 2.0.0 +**Estado**: En desarrollo activo 🚧 +**Última actualización**: Enero 2026 + +**Desarrollado con ❤️ para Bicicletería Lauck** \ No newline at end of file diff --git a/resources/views/catalogo/index.blade.php b/resources/views/catalogo/index.blade.php index 4e22482..6219ae8 100644 --- a/resources/views/catalogo/index.blade.php +++ b/resources/views/catalogo/index.blade.php @@ -6,7 +6,7 @@
@if ($products->count() > 0) -
+
@foreach ($products as $product)
{{-- Imagen si existe --}} diff --git a/resources/views/components/appc.blade.php b/resources/views/components/appc.blade.php index a054ae7..c1e4eaf 100644 --- a/resources/views/components/appc.blade.php +++ b/resources/views/components/appc.blade.php @@ -1,3 +1,6 @@ + +{{-- +DEPRECADO: Este componente ha sido reemplazado por layout.blade.php para una mejor organización. @props(['auth' => false]) @@ -120,4 +123,4 @@ }); - \ No newline at end of file + --}} \ No newline at end of file