2025-08-12 23:57:57 -03:00
2025-08-12 23:57:57 -03:00
2025-08-12 23:57:57 -03:00
2025-08-12 23:57:57 -03:00
2025-08-12 23:57:57 -03:00
2025-08-12 23:57:57 -03:00
2025-08-12 23:57:57 -03:00
2025-08-12 23:57:57 -03:00
2025-08-12 23:57:57 -03:00
2025-08-12 23:57:57 -03:00
2025-08-12 23:57:57 -03:00
2025-08-12 23:57:57 -03:00
2025-08-12 23:57:57 -03:00

🚴 Sistema de Gestión Lauck

Sistema web integral para gestión de bicicletería - Inventario, ventas, taller, clientes y catálogo público.

Laravel PHP Tailwind CSS 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)

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)

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

{
  "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

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

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

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

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

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)

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

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

PHP >= 8.2
Composer >= 2.x
Node.js >= 18.x
NPM >= 9.x
SQLite (o MySQL/PostgreSQL)

Instalación Paso a Paso

# 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:

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
# 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

// 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

// 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

// 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

// Para datasets grandes
$products = Product::latest()->cursorPaginate(20);

Refactorización de Código

1. Services para Lógica de Negocio

// 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

// 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

// 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

// 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

// 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

// En Form Request
protected function prepareForValidation()
{
    $this->merge([
        'name' => strip_tags($this->name),
        'description' => Purifier::clean($this->description),
    ]);
}

3. Protección CSRF Explícita

// Verificar en AJAX
$.ajaxSetup({
    headers: {
        'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
    }
});

4. Validación de Imágenes

'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

<button type="submit" id="submit-btn" class="...">
    <span class="loading hidden">
        <svg class="animate-spin h-5 w-5" ...></svg>
    </span>
    <span class="text">Guardar</span>
</button>

<script>
$('#form').on('submit', function() {
    $('#submit-btn .loading').removeClass('hidden');
    $('#submit-btn .text').addClass('hidden');
    $('#submit-btn').prop('disabled', true);
});
</script>

2. Confirmaciones Elegantes

// 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

// 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

$('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

// 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

// 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)

// 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:

$('.select2-product').select2('destroy'); // Destruir
const newRow = firstRow.clone(); // Clonar
initSelect2(); // Re-inicializar todos

Mejora sugerida:

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:

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

// 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

// 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 - El framework PHP para artesanos web
  • Tailwind CSS - Framework CSS utility-first
  • Select2 - Selectores avanzados
  • jQuery - 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

S
Description
Systema Interno de gestión para bicicleteria Lauck
Readme 3 MiB
Languages
Blade 66.1%
PHP 32.3%
JavaScript 1.2%
CSS 0.4%