edgar.mendez d1c203cd0e feat(warehouse): add inventory management features
- Implemented getWarehouseById method in warehouseService to fetch warehouse details by ID.
- Added new types for warehouse inventory management in warehouse.d.ts and warehouse.inventory.d.ts.
- Created WarehouseAddInventory.vue component for handling inventory entries with serial number management.
- Developed inventoryWarehouseServices for adding inventory through API.
- Updated router to include the new inventory management component.
- Added Docker configuration files for production deployment.
- Created Nginx configuration for serving the application.
- Added .dockerignore and .env.production for environment-specific settings.
2026-02-13 13:49:41 -06:00

448 lines
33 KiB
HTML

<!DOCTYPE html>
<html class="light" lang="es">
<head>
<meta charset="utf-8" />
<meta content="width=device-width, initial-scale=1.0" name="viewport" />
<title>Multi-Warehouse Goods Receipt Entry | Logistics Pro</title>
<script src="https://cdn.tailwindcss.com?plugins=forms,container-queries"></script>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;900&amp;display=swap"
rel="stylesheet" />
<link
href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&amp;display=swap"
rel="stylesheet" />
<script id="tailwind-config">
tailwind.config = {
darkMode: "class",
theme: {
extend: {
colors: {
"primary": "#137fec",
"background-light": "#f6f7f8",
"background-dark": "#101922",
},
fontFamily: {
"display": ["Inter"]
},
borderRadius: { "DEFAULT": "0.25rem", "lg": "0.5rem", "xl": "0.75rem", "full": "9999px" },
},
},
}
</script>
<style>
body {
font-family: 'Inter', sans-serif;
}
.material-symbols-outlined {
font-variation-settings: 'FILL' 0, 'wght' 400, 'GRAD' 0, 'opsz' 24;
}
</style>
</head>
<body class="bg-background-light dark:bg-background-dark font-display min-h-screen">
<div class="flex h-screen overflow-hidden">
<aside
class="w-64 bg-white dark:bg-slate-900 border-r border-slate-200 dark:border-slate-800 flex flex-col shrink-0">
<div class="p-6 flex items-center gap-3">
<div class="w-10 h-10 bg-primary rounded-lg flex items-center justify-center text-white">
<span class="material-symbols-outlined">inventory_2</span>
</div>
<div>
<h1 class="text-slate-900 dark:text-white text-base font-bold leading-none">Logistics Pro</h1>
<p class="text-slate-500 dark:text-slate-400 text-xs mt-1">Warehouse Admin</p>
</div>
</div>
<nav class="flex-1 px-4 py-4 space-y-1">
<a class="flex items-center gap-3 px-3 py-2 text-slate-600 dark:text-slate-400 hover:bg-slate-50 dark:hover:bg-slate-800 rounded-lg transition-colors"
href="#">
<span class="material-symbols-outlined">dashboard</span>
<span class="text-sm font-medium">Dashboard</span>
</a>
<a class="flex items-center gap-3 px-3 py-2 text-slate-600 dark:text-slate-400 hover:bg-slate-50 dark:hover:bg-slate-800 rounded-lg transition-colors"
href="#">
<span class="material-symbols-outlined">package_2</span>
<span class="text-sm font-medium">Inventario</span>
</a>
<a class="flex items-center gap-3 px-3 py-2 bg-primary/10 text-primary rounded-lg transition-colors"
href="#">
<span class="material-symbols-outlined"
style="font-variation-settings: 'FILL' 1">shopping_cart</span>
<span class="text-sm font-medium">Órdenes de Compra</span>
</a>
<a class="flex items-center gap-3 px-3 py-2 text-slate-600 dark:text-slate-400 hover:bg-slate-50 dark:hover:bg-slate-800 rounded-lg transition-colors"
href="#">
<span class="material-symbols-outlined">warehouse</span>
<span class="text-sm font-medium">Almacenes</span>
</a>
<a class="flex items-center gap-3 px-3 py-2 text-slate-600 dark:text-slate-400 hover:bg-slate-50 dark:hover:bg-slate-800 rounded-lg transition-colors"
href="#">
<span class="material-symbols-outlined">bar_chart</span>
<span class="text-sm font-medium">Reportes</span>
</a>
</nav>
<div class="p-4 border-t border-slate-200 dark:border-slate-800">
<div class="flex items-center gap-3 px-3 py-2">
<div class="size-8 rounded-full bg-slate-200 dark:bg-slate-700 bg-cover bg-center"
style="background-image: url('https://lh3.googleusercontent.com/aida-public/AB6AXuDa90XPiU0x0vWPCwSkY-b0XPWxuaglsKdsGDuVxfyQKkMYEU5M9ZhbSQkCrmRlRjYEiSLJ6gAeZWIORr6MFvWrYq-WoJFzzEUf18zJjkqmJK9oU270B7r6BRVz-ynoNSS6rUNF4_PE2az4uQgysTtym0Akce2JSv5s077kdSfpUvEYPzeMM4Oi9SSMG9kAIjTiQbCrRVUcE81w8a1TwD-JHuzmXutnjRS3BaPKKcT57SiJhYhoSkL1waAxm7SWR_fWDpTzxbnDlHnl')">
</div>
<div class="flex-1 min-w-0">
<p class="text-sm font-medium text-slate-900 dark:text-white truncate">Carlos Ruiz</p>
<p class="text-xs text-slate-500 truncate">Supervisor</p>
</div>
</div>
</div>
</aside>
<main class="flex-1 flex flex-col min-w-0 overflow-hidden">
<header
class="h-16 bg-white dark:bg-slate-900 border-b border-slate-200 dark:border-slate-800 flex items-center justify-between px-8 shrink-0">
<div class="flex items-center gap-4">
<div class="flex items-center gap-2 text-slate-400 text-sm font-medium">
<a class="hover:text-primary" href="#">Inicio</a>
<span class="material-symbols-outlined text-xs">chevron_right</span>
<a class="hover:text-primary" href="#">Órdenes de Compra</a>
<span class="material-symbols-outlined text-xs">chevron_right</span>
<span class="text-slate-900 dark:text-white">Registrar Entrada (Multialmacén)</span>
</div>
</div>
<div class="flex items-center gap-4">
<div class="relative w-64">
<span
class="material-symbols-outlined absolute left-3 top-1/2 -translate-y-1/2 text-slate-400 text-lg">search</span>
<input
class="w-full pl-10 pr-4 py-1.5 bg-slate-100 dark:bg-slate-800 border-none rounded-lg text-sm focus:ring-2 focus:ring-primary/20"
placeholder="Buscar PO, SKU..." type="text" />
</div>
<button class="p-2 text-slate-400 hover:text-slate-600 dark:hover:text-white">
<span class="material-symbols-outlined">notifications</span>
</button>
<button class="p-2 text-slate-400 hover:text-slate-600 dark:hover:text-white">
<span class="material-symbols-outlined">settings</span>
</button>
</div>
</header>
<div class="flex-1 overflow-y-auto p-8">
<div class="max-w-7xl mx-auto space-y-6">
<div class="flex flex-col md:flex-row md:items-end justify-between gap-4">
<div>
<h2 class="text-3xl font-black text-slate-900 dark:text-white tracking-tight">Registrar
Entrada de Mercancía</h2>
<p class="text-slate-500 dark:text-slate-400 mt-1 flex items-center gap-2">
<span class="material-symbols-outlined text-base">receipt_long</span>
Purchase Order #ORD-2023-001 | <span class="text-primary font-semibold">Distribución
Multi-Almacén</span>
</p>
</div>
<div class="flex items-center gap-3">
<div
class="flex gap-4 bg-white dark:bg-slate-900 px-4 py-2 rounded-lg border border-slate-200 dark:border-slate-800 shadow-sm">
<div class="text-center">
<p class="text-[10px] text-slate-500 uppercase tracking-wider font-bold">Total Items
PO</p>
<p class="text-lg font-black text-slate-900 dark:text-white leading-tight">12</p>
</div>
<div class="w-px bg-slate-200 dark:bg-slate-800 h-8 self-center"></div>
<div class="text-center">
<p class="text-[10px] text-slate-500 uppercase tracking-wider font-bold">Recibidos
</p>
<p class="text-lg font-black text-primary leading-tight">0</p>
</div>
</div>
<button
class="inline-flex items-center gap-2 px-4 py-2 bg-slate-200 dark:bg-slate-800 text-slate-700 dark:text-slate-200 font-bold text-sm rounded-lg hover:bg-slate-300 transition-colors">
<span class="material-symbols-outlined text-lg">visibility</span>
Ver Detalles
</button>
</div>
</div>
<div
class="bg-white dark:bg-slate-900 rounded-xl border border-slate-200 dark:border-slate-800 shadow-sm overflow-hidden">
<div
class="px-6 py-4 border-b border-slate-200 dark:border-slate-800 bg-slate-50/50 dark:bg-slate-800/50 flex justify-between items-center">
<h3 class="font-bold text-slate-900 dark:text-white">Productos de la Orden</h3>
<span class="text-xs text-slate-500 flex items-center gap-1">
<span class="material-symbols-outlined text-sm">info</span>
Seleccione el almacén de destino por cada producto
</span>
</div>
<div class="overflow-x-auto">
<table class="w-full border-collapse">
<thead>
<tr
class="text-left text-xs font-bold text-slate-500 dark:text-slate-400 uppercase tracking-wider bg-slate-50 dark:bg-slate-800/30">
<th class="px-6 py-4">Producto</th>
<th class="px-6 py-4">SKU / Ref</th>
<th class="px-6 py-4 text-center">Cant. PO</th>
<th class="px-6 py-4 text-center">Recibida</th>
<th class="px-6 py-4">Almacén de Destino</th>
<th class="px-6 py-4">Acciones</th>
</tr>
</thead>
<tbody class="divide-y divide-slate-200 dark:divide-slate-800">
<tr class="group hover:bg-slate-50 dark:hover:bg-slate-800/50 transition-colors">
<td class="px-6 py-4">
<div class="flex items-center gap-3">
<div
class="size-10 bg-slate-100 dark:bg-slate-800 rounded-lg flex items-center justify-center text-slate-400">
<span class="material-symbols-outlined">inventory</span>
</div>
<div class="flex flex-col">
<span
class="text-sm font-semibold text-slate-900 dark:text-white">Cables
de Red Cat6 2m</span>
<span class="text-xs text-slate-500">Accesorios Networking</span>
</div>
</div>
</td>
<td class="px-6 py-4 text-sm text-slate-600 dark:text-slate-400">NET-C62M-WH
</td>
<td
class="px-6 py-4 text-center text-sm font-bold text-slate-900 dark:text-white">
50</td>
<td class="px-6 py-4">
<div class="flex justify-center">
<input
class="w-20 text-center px-2 py-1 bg-slate-100 dark:bg-slate-800 border-none rounded-lg text-sm font-bold focus:ring-2 focus:ring-primary"
max="50" min="0" type="number" value="0" />
</div>
</td>
<td class="px-6 py-4">
<select
class="w-full px-3 py-1.5 bg-slate-50 dark:bg-slate-800 border border-slate-200 dark:border-slate-700 rounded-lg text-xs focus:ring-primary focus:border-primary">
<option value="">Seleccione Almacén...</option>
<option selected="" value="1">Almacén Principal (CDMX)</option>
<option value="2">Bodega Regional (MTY)</option>
<option value="3">CEDIS (GDL)</option>
</select>
</td>
<td class="px-6 py-4">
<span
class="inline-flex items-center px-2.5 py-0.5 rounded-full text-[10px] font-bold bg-slate-100 text-slate-600 dark:bg-slate-800 dark:text-slate-400 uppercase">Estándar</span>
</td>
</tr>
<tr class="bg-primary/[0.02] dark:bg-primary/[0.05]">
<td class="px-6 py-4 border-l-4 border-primary">
<div class="flex items-center gap-3">
<div
class="size-10 bg-primary/10 rounded-lg flex items-center justify-center text-primary">
<span class="material-symbols-outlined">laptop_mac</span>
</div>
<div class="flex flex-col">
<span
class="text-sm font-semibold text-slate-900 dark:text-white">MacBook
Pro M2 14"</span>
<span class="text-xs text-slate-500">Equipos de Cómputo</span>
</div>
</div>
</td>
<td class="px-6 py-4 text-sm text-slate-600 dark:text-slate-400">LAP-MBP14-M2
</td>
<td
class="px-6 py-4 text-center text-sm font-bold text-slate-900 dark:text-white">
5</td>
<td class="px-6 py-4 text-center">
<span class="text-sm font-black text-primary">1 / 5</span>
</td>
<td class="px-6 py-4">
<div class="text-xs text-slate-400 italic">Asignación por número de serie
</div>
</td>
<td class="px-6 py-4">
<button
class="inline-flex items-center gap-2 px-3 py-1.5 bg-primary text-white text-xs font-bold rounded-lg hover:bg-primary/90 transition-all shadow-sm">
<span class="material-symbols-outlined text-sm">barcode_scanner</span>
GESTIONAR SERIES
</button>
</td>
</tr>
<tr class="bg-primary/[0.02] dark:bg-primary/[0.05]">
<td class="px-10 pb-6 pt-2" colspan="6">
<div
class="bg-white dark:bg-slate-800 rounded-xl border border-primary/20 p-5 shadow-sm">
<div
class="flex items-center justify-between mb-4 pb-3 border-b border-slate-100 dark:border-slate-700">
<div>
<h4
class="text-sm font-bold text-slate-700 dark:text-slate-200">
Entrada de Números de Serie (4 Pendientes)</h4>
<p class="text-[11px] text-slate-500">Defina el almacén para
cada equipo escaneado</p>
</div>
<div
class="flex items-center gap-2 text-xs text-primary font-bold bg-primary/10 px-3 py-1.5 rounded-full">
<span class="material-symbols-outlined text-sm">barcode</span>
Listo para escanear
</div>
</div>
<div class="grid grid-cols-1 lg:grid-cols-12 gap-6">
<div class="lg:col-span-5 space-y-4">
<div>
<label
class="block text-[10px] font-bold text-slate-500 uppercase mb-1">Número
de Serie</label>
<div class="relative">
<span
class="material-symbols-outlined absolute left-3 top-1/2 -translate-y-1/2 text-slate-400">qr_code_scanner</span>
<input
class="w-full pl-10 pr-4 py-2 bg-slate-50 dark:bg-slate-700 border border-slate-200 dark:border-slate-600 rounded-lg text-sm focus:ring-primary focus:border-primary"
placeholder="Escanear o escribir serie..."
type="text" />
</div>
</div>
<div>
<label
class="block text-[10px] font-bold text-slate-500 uppercase mb-1">Almacén
Destino</label>
<select
class="w-full px-3 py-2 bg-slate-50 dark:bg-slate-700 border border-slate-200 dark:border-slate-600 rounded-lg text-sm focus:ring-primary focus:border-primary">
<option value="1">Almacén Principal (CDMX)</option>
<option value="2">Bodega Regional (MTY)</option>
<option value="3">CEDIS (GDL)</option>
</select>
</div>
<button
class="w-full py-2 bg-slate-900 dark:bg-slate-700 text-white text-xs font-bold rounded-lg hover:bg-black transition-colors">
Registrar Serie
</button>
</div>
<div class="lg:col-span-7">
<div
class="bg-slate-50 dark:bg-slate-900/50 rounded-lg border border-slate-200 dark:border-slate-700 overflow-hidden">
<table class="w-full text-xs">
<thead class="bg-slate-100 dark:bg-slate-800">
<tr>
<th
class="px-3 py-2 text-left font-bold text-slate-500 uppercase">
Nº Serie</th>
<th
class="px-3 py-2 text-left font-bold text-slate-500 uppercase">
Almacén Destino</th>
<th class="px-3 py-2 text-right"></th>
</tr>
</thead>
<tbody
class="divide-y divide-slate-200 dark:divide-slate-700">
<tr>
<td
class="px-3 py-2 font-mono text-slate-900 dark:text-white">
SN-LAP-M2-00192</td>
<td class="px-3 py-2">
<span
class="inline-flex items-center gap-1.5">
<span
class="w-2 h-2 rounded-full bg-emerald-500"></span>
<span
class="text-slate-600 dark:text-slate-300">Almacén
Principal (CDMX)</span>
</span>
</td>
<td class="px-3 py-2 text-right">
<button
class="text-slate-400 hover:text-red-500 transition-colors">
<span
class="material-symbols-outlined text-lg">delete</span>
</button>
</td>
</tr>
<tr>
<td class="px-3 py-4 text-center text-slate-400 italic bg-slate-50/50 dark:bg-slate-800/30"
colspan="3">
Escanee el siguiente equipo para asignar
almacén...
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</td>
</tr>
<tr class="group hover:bg-slate-50 dark:hover:bg-slate-800/50 transition-colors">
<td class="px-6 py-4">
<div class="flex items-center gap-3">
<div
class="size-10 bg-slate-100 dark:bg-slate-800 rounded-lg flex items-center justify-center text-slate-400">
<span class="material-symbols-outlined">print</span>
</div>
<div class="flex flex-col">
<span
class="text-sm font-semibold text-slate-900 dark:text-white">Impresora
Zebra ZT411</span>
<span class="text-xs text-slate-500">Hardware Almacén</span>
</div>
</div>
</td>
<td class="px-6 py-4 text-sm text-slate-600 dark:text-slate-400">PRN-ZB411-IND
</td>
<td
class="px-6 py-4 text-center text-sm font-bold text-slate-900 dark:text-white">
2</td>
<td class="px-6 py-4 text-center text-sm font-bold text-slate-400">0 / 2</td>
<td class="px-6 py-4">
<div class="text-xs text-slate-400 italic">Asignación por serie requerida
</div>
</td>
<td class="px-6 py-4">
<button
class="inline-flex items-center gap-2 px-3 py-1.5 border border-slate-200 dark:border-slate-700 text-slate-600 dark:text-slate-300 text-xs font-bold rounded-lg hover:bg-slate-100 dark:hover:bg-slate-800 transition-colors">
<span class="material-symbols-outlined text-sm">barcode_scanner</span>
GESTIONAR SERIES
</button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
<div
class="md:col-span-2 bg-amber-50 dark:bg-amber-900/20 border border-amber-200 dark:border-amber-900/50 p-4 rounded-xl flex items-start gap-4">
<span class="material-symbols-outlined text-amber-600 dark:text-amber-500">warning</span>
<div>
<p class="text-sm font-bold text-amber-800 dark:text-amber-400">Pendiente de Validación
y Distribución</p>
<p class="text-sm text-amber-700 dark:text-amber-500/80">Faltan registrar 6 números de
serie y asignar almacén de destino a 1 item de tipo estándar antes de confirmar.</p>
</div>
</div>
<div
class="bg-white dark:bg-slate-900 p-4 rounded-xl border border-slate-200 dark:border-slate-800 shadow-sm">
<h4 class="text-xs font-bold text-slate-500 uppercase tracking-wider mb-3">Resumen de
Destinos</h4>
<div class="space-y-2">
<div class="flex justify-between text-xs">
<span class="text-slate-600 dark:text-slate-400">Almacén Principal (CDMX)</span>
<span class="font-bold text-slate-900 dark:text-white">1 Unidad</span>
</div>
<div class="flex justify-between text-xs">
<span class="text-slate-600 dark:text-slate-400">Bodega Regional (MTY)</span>
<span class="font-bold text-slate-900 dark:text-white">0 Unidades</span>
</div>
<div class="flex justify-between text-xs">
<span class="text-slate-600 dark:text-slate-400">CEDIS (GDL)</span>
<span class="font-bold text-slate-900 dark:text-white">0 Unidades</span>
</div>
</div>
</div>
</div>
</div>
</div>
<footer
class="h-20 bg-white dark:bg-slate-900 border-t border-slate-200 dark:border-slate-800 flex items-center justify-end px-8 gap-4 shrink-0">
<button
class="px-6 py-2.5 text-sm font-bold text-slate-600 dark:text-slate-400 hover:text-slate-900 dark:hover:text-white transition-colors">
Cancelar
</button>
<button
class="px-8 py-2.5 bg-primary text-white text-sm font-bold rounded-lg shadow-lg shadow-primary/20 hover:bg-primary/90 transition-all opacity-50 cursor-not-allowed">
Confirmar Recepción Multi-Almacén
</button>
</footer>
</main>
</div>
</body>
</html>