# 🚴 Sistema de Gestión Lauck
**Sistema web integral para gestión de bicicletería** - Inventario, ventas, taller, clientes y catálogo público.
[](https://laravel.com)
[](https://php.net)
[](https://tailwindcss.com)
[](LICENSE)
## 📋 Descripción
**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.
## ✨ Características Principales
### 🔐 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
### 📦 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
#### 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
### 💰 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
#### 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
#### 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
### 👥 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
### 🔧 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
#### 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
#### 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
#### 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
### 🌐 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
#### 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
### 🎨 Sistema de Diseño
#### 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
#### 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
Bryam - Desarrollo particular de Bryam
Lucas - Desarrollo particular de Lucas
Giane - Desarrollo particular de Giane
```
## 🤝 Contribuir
### Proceso
1. Fork del proyecto
2. Crear rama: `git checkout -b (Tu Nombre)`
3. Commit: `git commit -m 'Add: nueva funcionalidad'`
4. Push: `git push origin (Tu Nombre)`
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**