# WMS — Checklist de revisión end-to-end (2026-05-16)

> Recorre el módulo completo después del refactor + rescate R-1..R-9 + sesiones S-1..S-6.
> Marcá cada item al ir probando. Si algo no anda, dejá tu comentario en el bloque correspondiente; al cerrar la revisión los juntamos en una sesión "S-8 fixes".
>
> **Cómo usar este doc:** podés editar este archivo directamente, marcar `[x]` lo que funcione y escribir bajo "💬 Comentarios" lo que no. Después commiteás los cambios y revisamos juntos.

---

## 0. Setup previo (obligatorio antes de empezar)

### 0.1 Servicios
- [ ] Backend Laravel corriendo: `cd C:\xampp\htdocs\api-a-conta && php artisan serve` (o XAMPP).
- [ ] Frontend Nuxt corriendo: `cd C:\xampp\htdocs\aconta && npm run dev`.
- [ ] Login OK con un usuario que tenga `par_empresa_id` válido.

### 0.2 Datos base mínimos (deben existir antes de seedear artículos)
- [ ] Al menos una `par_empresa` activa.
- [ ] Al menos una `pos_bodega` activa de esa empresa.
- [ ] Layout WMS activo para esa bodega (si no existe, abrir `/pos/wms/layout`, elegir la bodega y "Crear layout").

### 0.3 Seedear artículos de prueba
Ejecutar desde `C:\xampp\htdocs\api-a-conta`:

```powershell
WITH_BODEGA=1 WITH_EMPAQUES=1 php artisan db:seed --class=PosArticulosWmsDemoSeeder
```

Esto crea:
- **15 artículos** con SKUs `WMS-A001..A005` (perecibles), `WMS-N001..N003` (no perecibles), `WMS-L001/L002` (limpieza), `WMS-F001..F003` (ferretería), `WMS-E001/E002` (electrónica). Todos con `requiere_gestion_wms=1`.
- **Pivote** en todas las bodegas activas de la empresa (stock=0).
- **Empaque primario** con dimensiones y peso realistas por SKU.

Verificación:
- [ ] El comando reporta "15 nuevos / X pivotes / 15 empaques nuevos".
- [ ] Los artículos aparecen en `/pos/wms/empaques` con sus dimensiones.

### 0.4 Diagnóstico inicial
```powershell
php artisan wms:verificar-integracion
```
- [ ] Output muestra "Estado integración: OK" con 8 checks en verde.
- [ ] Reporta 1+ bodega con layout activo y 15 artículos con `requiere_gestion_wms=1`.

> 💬 **Comentarios setup:**
>
>

---

## 1. Empaques de artículos

Ruta: `/pos/wms/empaques`

- [ ] Tabla lista los 15 empaques creados por el seeder.
- [ ] Filtro por tipo (primario/interno/caja/pallet) funciona.
- [ ] Crear empaque nuevo: botón "Nuevo" → modal con artículo, tipo, dimensiones, peso. Guarda OK.
- [ ] Editar empaque existente: cambiar `orientacion_descripcion` (libre o preset). Guarda.
- [ ] Eliminar empaque: soft-delete (desaparece de la lista).

> 💬 **Comentarios empaques:**
>
>

---

## 2. Reglas de slotting

Ruta: `/pos/wms/reglas-slotting`

- [ ] Lista por bodega.
- [ ] Crear regla nueva **sin elegir estrategia**: el backend autoconfigura según `par_empresas.metodo_inventario_id` (PMP→ABC/FEFO, FIFO→FIFO/FEFO, etc.). Verificar que la regla creada tenga estrategia coherente.
- [ ] Crear regla eligiendo estrategia manual (override): respeta lo elegido.
- [ ] Toggle `auto_sugerir`: cuando está ON, al asignar stock desde la vista lateral del rack el sistema sugiere automáticamente sin pedirlo.

> 💬 **Comentarios reglas slotting:**
>
>

---

## 3. Pisos

Ruta: `/pos/wms/pisos`

- [ ] Filtro por bodega muestra solo pisos de esa bodega.
- [ ] Crear piso: número, nombre (ej. "Planta baja"), color. Guarda.
- [ ] Editar piso: cambiar nombre y color.
- [ ] Eliminar piso: soft-delete. Verificar que racks/zonas asociados no quedan huérfanos (su `wms_piso_id` queda NULL por el `nullOnDelete`).

> 💬 **Comentarios pisos:**
>
>

---

## 4. Editor 2D (CAD)

Ruta: `/pos/wms/layout/{bodegaId}` (entrar desde `/pos/wms/layout`)

### 4.1 Carga inicial
- [ ] Si la bodega no tiene layout, aparece botón para crearlo.
- [ ] Con layout, se carga canvas vacío y toolbar con todos los modos.

### 4.2 Dibujar habitación
- [ ] Botón **"Dibujar habitación"** (atajo P) activa modo polígono.
- [ ] Click en el canvas agrega vértices con snap (vértice/midpoint/ortho).
- [ ] Toggle **Ortho** (atajo O) fuerza ángulos de 45° desde el último vértice.
- [ ] **Z** deshace último vértice.
- [ ] **Enter** o doble-click cierra el polígono (mínimo 3 vértices) → habitación creada.
- [ ] **Esc** cancela el draft sin guardar.

### 4.3 Editar aristas
- [ ] Click sobre el label de una arista abre prompt para editar la distancia real (m). Guarda.
- [ ] Click sobre el body de una arista en modo **select** abre panel lateral con tipo (borde_habitacion/pared/guia), distancia real, y si tipo=pared también grosor y subtipo.

### 4.4 Arrastrar vértices
- [ ] Modo **edit-vertex** (atajo V) hace los vértices draggable.
- [ ] Al soltar un vértice, snap a otros vértices cercanos. Las aristas se redibujan.
- [ ] Las distancias reales de las aristas conectadas NO cambian (decisión de diseño).

### 4.5 Aberturas
- [ ] Modo **Abertura** (atajo A) + click sobre una arista tipo=pared → modal con tipo (puerta/ventana/vano/portón), ancho, posición desde inicio, alto, sentido apertura.
- [ ] Validación: `posicion + ancho ≤ distancia_real_m`.
- [ ] La abertura aparece como rectángulo de color sobre la pared (blanco/azul puerta, celeste ventana, etc.).
- [ ] Click sobre la abertura → modal info con opción Eliminar.

### 4.6 Elementos arquitectónicos
- [ ] Dropdown **Elemento** con tipos columna/escalera/muelle/otro (atajo E).
- [ ] Click en el canvas crea el elemento con modal de dimensiones + rotación.
- [ ] Aparece como rectángulo con letra (C/E/M/?) y color por tipo.
- [ ] Click → info + eliminar.

### 4.7 Racks
- [ ] Botón **Rack** + click en el canvas → modal con código, tipo, dimensiones, niveles, rotación, material.
- [ ] Al crear con `niveles_count > 0`, los niveles + ubicaciones se generan automáticamente (verificar que el modal de info muestre la tabla de niveles con códigos `R-XX-N1`, `R-XX-N2`, etc.).
- [ ] Click sobre el rack abre modal con datos + tabla de niveles + 3 botones: Eliminar, **Vista lateral** (azul, navega a `/pos/wms/racks/{id}/elevacion`), Cerrar.

### 4.8 Zonas operativas
- [ ] Dropdown **Zona** con 7 tipos (recepción/almacenamiento/picking/despacho/staging/devolución/otra).
- [ ] Click en el canvas → modal con nombre, ancho, largo, rotación, prioridad.
- [ ] Aparece como rectángulo semitransparente con color por tipo. Click → info + eliminar.

### 4.9 Drag-drop de artículos al canvas (S-5 nuevo)
- [ ] Botón **Artículos** en la toolbar muestra el panel de empaques a la izquierda.
- [ ] Búsqueda por SKU o nombre filtra la lista.
- [ ] Arrastrar un artículo y soltarlo **encima de un rack** abre modal de asignación con todas las ubicaciones del rack (etiquetadas `N{nivel} · {código}`).
- [ ] Soltar fuera de un rack → mensaje "Soltá sobre un rack".
- [ ] Confirmar el modal con uds/costo/lote/vencimiento → crea stock + WmsMovimiento tipo=ajuste.

### 4.10 Navegación / vista
- [ ] **Ctrl+wheel** zoom (rango 0.2× a 5×, centrado en el cursor).
- [ ] **Click medio + drag** pan del canvas.
- [ ] **R** reset vista.
- [ ] Stats abajo muestran v · e · h · ab · el · rk · zn correctos.

### 4.11 PUT snapshot (R-9)
> Esto se prueba solo si hay un botón "Guardar todo" en algún lugar del editor. Si no lo hay aún, queda como TODO.
- [ ] _(N/A si no hay UI)_

> 💬 **Comentarios editor 2D:**
>
>

---

## 5. Listado de racks

Ruta: `/pos/wms/racks`

- [ ] Filtro por bodega muestra solo racks de esa bodega.
- [ ] Tabla lista código, tipo, material, niveles_count, capacidad, dimensiones.
- [ ] Botón **Vista lateral** (por fila) navega a la elevación.
- [ ] Botón **Niveles** (por fila) abre modal con tabla editable de niveles (alto, largo, ancho, capacidad, divisiones, tipo_almacén).
- [ ] Editar valores en la tabla y "Guardar cambios" → PUT por nivel.
- [ ] Botón trash por nivel → DELETE con cascade a ubicaciones.

### 5.1 Subdividir nivel (S-4 nuevo)
- [ ] Ícono **grid 3×3** por fila abre sub-modal "Subdividir nivel N{n}".
- [ ] Input "Divisiones" (1-10) + input opcional "Subdivisiones por división" (CSV, ej `2,1,2`).
- [ ] Si CSV vacío → 1 subdivisión por división.
- [ ] Si CSV no coincide con cantidad de divisiones → validation error.
- [ ] Aplicar: si hay stock activo, rechaza con "No se puede subdividir: hay stock activo".
- [ ] Si no hay stock, regenera ubicaciones con códigos `{rack}-N{n}-D{d}` o `-D{d}-S{s}`.
- [ ] Verificar en BD: `wms_rack_nivel_subdivisiones` tiene las filas con dimensiones repartidas.

> 💬 **Comentarios racks + niveles + subdividir:**
>
>

---

## 6. Vista lateral del rack (`/pos/wms/racks/{id}/elevacion`)

### 6.1 Canvas
- [ ] Canvas vertical muestra los niveles apilados (nivel 1 abajo).
- [ ] Cada nivel muestra capacidad, % ocupación, líneas de divisiones/subdivisiones.
- [ ] Click sobre un nivel lo selecciona (borde verde).

### 6.2 Panel derecho
- [ ] Card "Datos del rack" muestra tipo, material, dimensiones, capacidad.
- [ ] `PanelOcupacion` muestra barras % por nivel; resalta rojo si ≥95%.

### 6.3 Drag-drop desde panel artículos (R-2b)
- [ ] Panel izquierdo lista los empaques con búsqueda.
- [ ] Drag de un artículo a un nivel → abre modal de asignación.
- [ ] Modal pre-fillea ubicación del nivel destino.
- [ ] Botón **"Sugerir ubicación"** → POST `wmsSlotting/sugerencia` (modo putaway), muestra sugerencia y permite usarla.
- [ ] Si la regla de la bodega tiene `auto_sugerir=true`, la sugerencia carga sola al abrir el modal.
- [ ] Inputs uds/costo/lote/vencimiento + Confirmar → crea `wms_ubicacion_stocks` + WmsMovimiento.

### 6.4 Tabla "Contenido del nivel"
- [ ] Muestra solo las líneas del nivel seleccionado.
- [ ] Columna acciones con botón **trash** elimina la línea (DELETE + WmsMovimiento tipo=ajuste por las unidades).

> 💬 **Comentarios vista lateral:**
>
>

---

## 7. Tareas WMS

Ruta: `/pos/wms/operaciones/tareas`

### 7.1 Generación automática (vía observer POS↔WMS)
- [ ] **Test E2E manual:** crear una venta en POS (`/pos/ventas/ventas`) que incluya 1+ artículos `WMS-*` con stock disponible en la bodega WMS. Al cerrar la venta, una tarea pick_list aparece en `/pos/wms/operaciones/tareas` con líneas según estrategia de slotting de la bodega.
- [ ] Idem compra → put_list.
- [ ] Si el artículo no tiene `requiere_gestion_wms=1` o la bodega no tiene layout, NO se genera tarea (esperado).

### 7.2 Completar línea
- [ ] Botón "Iniciar tarea" cambia estado a en_proceso.
- [ ] Botón "Completar" por línea → modal con código de ubicación (editable), unidades, costo, lote.
- [ ] Botón **escáner QR** (ícono qr-code-scan) al lado del input ubicación abre overlay con cámara (atención: requiere HTTPS o localhost).
- [ ] Confirmar línea → stock descontado/agregado + WmsMovimiento + línea marcada completada (o parcial si solo se hizo parte).
- [ ] Cuando todas las líneas están completadas, la tarea cambia a completada.

### 7.3 Cancelar tarea
- [ ] Botón cancelar marca `estado_tarea='cancelada'`, `estado=0`.

### 7.4 Validación lote ID específica (S-3 nuevo)
- [ ] Si la empresa tiene `par_empresas.metodo_inventario_id=4` (ID específica), completar una línea de pick_list **con lote distinto al físico** debe rechazar con "Lote físico no coincide con lote contable".
- [ ] Si `metodo_inventario_id != 4`, el lote NO se valida cruzado (comportamiento original).

> 💬 **Comentarios tareas:**
>
>

---

## 8. Ajustes manuales de stock

Ruta: `/pos/wms/operaciones/ajustes-stock`

- [ ] Filtros bodega + búsqueda artículo funcionan.
- [ ] Tabla lista los stocks con ubicación, sku, nombre, unidades, lote, vencimiento, costo.
- [ ] **Nuevo ajuste**: modal con selector ubicación + artículo + uds + costo + lote opt + vencimiento opt + observación. Confirma → crea o consolida `wms_ubicacion_stocks` + WmsMovimiento tipo=ajuste con `ref_tipo=ajuste_manual`.
- [ ] **Editar** (ícono lápiz) cambia uds y costo. Genera WmsMovimiento por el delta con signo correcto (destino si suma, origen si resta).
- [ ] **Eliminar** soft-delete + WmsMovimiento por las unidades que estaban.

> 💬 **Comentarios ajustes manuales:**
>
>

---

## 9. Conteo cíclico

Ruta: `/pos/wms/operaciones/conteo`

- [ ] Filtro por bodega.
- [ ] Botón **"Nuevo conteo"** → modal con bodega + observación. Al confirmar, genera una línea por cada `wms_ubicacion_stocks` con `stock > 0` de esa bodega. `unidades_solicitadas` = stock actual.
- [ ] Si la bodega no tiene stock → "Sin stock para contar".
- [ ] Card por tarea muestra tabla con # · ubicación · artículo · esperado · contado · Δ · estado.
- [ ] Botón "Iniciar" cambia a en_proceso.
- [ ] Botón **"Contar"** por línea → modal con input unidades. Si difiere → genera WmsMovimiento ajuste por el delta (signo según diferencia). Si coincide → marca completada sin movimiento.
- [ ] Columna Δ visible con color verde (+) o rojo (-) al cerrar línea.

> 💬 **Comentarios conteo:**
>
>

---

## 10. Reportes

### 10.1 Ocupación — `/pos/wms/reportes/ocupacion`
- [ ] Filtros bodega + "agrupar por" (rack/nivel/zona).
- [ ] Cards totales: capacidad total, peso ocupado, % ocupado.
- [ ] Gráfico de barras por grupo.
- [ ] Tabla con ubicaciones totales/ocupadas, % por barra de color (verde <70%, amarillo 70-90%, rojo ≥95%).
- [ ] Excel exporta OK con todos los datos.

### 10.2 Rotación — `/pos/wms/reportes/rotacion`
- [ ] Filtros bodega + rango de fechas + top N.
- [ ] Tabla ranking por unidades salidas (picking), con turnover y clase ABC.
- [ ] Excel exporta OK.

### 10.3 Vencimientos — `/pos/wms/reportes/vencimientos`
- [ ] Filtros bodega + días umbral.
- [ ] Tabla con lotes próximos a vencer, columna "días restantes" + urgencia (vencido/crítico/alerta/normal).
- [ ] Color de fila según urgencia (rojo vencido/crítico, amarillo alerta).
- [ ] Excel exporta con colores.

### 10.4 Costo contable vs físico (S-6 nuevo) — `/pos/wms/reportes/costo-contable-vs-fisico`
- [ ] Filtros bodega + umbral % (default 1).
- [ ] Cards: artículos con divergencia, sobrante, |Δ valor| total.
- [ ] Tabla muestra SKU/artículo/bodega/stock POS/stock WMS/costo POS/costo WMS ponderado/Δ abs/Δ %/Δ valor.
- [ ] Filas con fondo rojo si |Δ valor| > 10.000 CLP, amarillo > 1.000 CLP.
- [ ] Excel exporta con colores.
- [ ] Si bajás el umbral a 0 lista todo (sin filtrar).

> 💬 **Comentarios reportes:**
>
>

---

## 11. Comandos consola

### 11.1 `wms:reconcile`
```powershell
php artisan wms:reconcile
php artisan wms:reconcile --bodega=5
```
- [ ] Sin diferencias → "Sin diferencias entre WMS y POS" (exit 0).
- [ ] Con diferencias → tabla con bodega/artículo/stock POS/stock WMS/diferencia + exit 1.
- [ ] Filtro por bodega funciona.

### 11.2 `wms:verificar-integracion`
```powershell
php artisan wms:verificar-integracion
php artisan wms:verificar-integracion --bodega=5 --simular=venta --articulo=10 --cantidad=2
```
- [ ] Sin args: 8 checks + reporta bodegas con layout + artículos con flag + tareas pendientes.
- [ ] Con `--simular=venta`: crea PosInventario de prueba dentro de transacción, reporta si el observer generó tarea, rollback al final (no persiste).
- [ ] Con `--simular=compra`: idem para put_list.

> 💬 **Comentarios comandos consola:**
>
>

---

## 12. Edge cases y comportamiento defensivo

- [ ] Crear rack sin niveles (`niveles_count=0`): NO se generan ubicaciones; rack queda sin operativa hasta editarlo.
- [ ] Cambiar `niveles_count` de un rack con stock activo: rechaza con HTTP 422.
- [ ] Cambiar `niveles_count` de un rack sin stock: regenera todo, ubicaciones nuevas con códigos correlativos.
- [ ] Eliminar rack (soft-delete): cascade marca niveles + ubicaciones también con `estado=0`.
- [ ] Subdividir nivel con stock activo: rechaza con HTTP 422 + mensaje claro.
- [ ] Pivote `pos_bodega_articulos` faltante para un artículo: la venta debería fallar antes de llegar al observer (POS lo valida). Comportamiento esperado.

> 💬 **Comentarios edge cases:**
>
>

---

## 13. Performance (opcional, si tenés tiempo)

- [ ] Editor 2D con 50+ racks: zoom/pan fluido (>30 FPS).
- [ ] Listado de tareas con 100+ tareas pendientes: carga en <2s.
- [ ] Reporte costo contable con 1000+ artículos: carga en <5s.

> 💬 **Comentarios performance:**
>
>

---

## Resumen al cierre

### Lo que funcionó bien
>
>

### Bugs encontrados (lista para "S-8 fixes")
1.
2.
3.

### Mejoras / pulido sugerido
1.
2.
3.

### Decisiones que quedan abiertas
1.
2.
