diff --git a/pos/static/js/inventory.js b/pos/static/js/inventory.js
index c0a0228..8835ef8 100644
--- a/pos/static/js/inventory.js
+++ b/pos/static/js/inventory.js
@@ -1,90 +1,133 @@
// /home/Autopartes/pos/static/js/inventory.js
-// Inventory management UI: CRUD, purchases, adjustments, transfers, physical count, alerts
+// Inventory management UI — rewritten to match design-system HTML structure
+// Panels: panel-stock, panel-entradas, panel-salidas, panel-traspasos, panel-ajustes, panel-conteos, panel-alertas
(function () {
'use strict';
- const API = '/pos/api/inventory';
- const token = localStorage.getItem('pos_token');
+ var API = '/pos/api/inventory';
+ var token = localStorage.getItem('pos_token');
if (!token) { window.location.href = '/pos/login'; return; }
- const headers = { 'Authorization': 'Bearer ' + token, 'Content-Type': 'application/json' };
- let currentPage = 1;
- let currentSearch = '';
- let draftCountId = null;
+ var headers = { 'Authorization': 'Bearer ' + token, 'Content-Type': 'application/json' };
+ var currentPage = 1;
+ var currentSearch = '';
+ var draftCountId = null;
// --- API helper ---
- async function apiFetch(url, opts) {
- const resp = await fetch(url, Object.assign({ headers: headers }, opts || {}));
- if (resp.status === 401) { localStorage.removeItem('pos_token'); window.location.href = '/pos/login'; return null; }
- return resp.json();
+ function apiFetch(url, opts) {
+ return fetch(url, Object.assign({ headers: headers }, opts || {}))
+ .then(function (resp) {
+ if (resp.status === 401) {
+ localStorage.removeItem('pos_token');
+ window.location.href = '/pos/login';
+ return null;
+ }
+ return resp.json();
+ });
}
- // --- Tab switching ---
- document.querySelectorAll('.tab').forEach(function (tab) {
- tab.addEventListener('click', function () {
- document.querySelectorAll('.tab').forEach(function (t) { t.classList.remove('active'); });
- document.querySelectorAll('.tab-content').forEach(function (c) { c.classList.remove('active'); });
- tab.classList.add('active');
- document.getElementById('tab-' + tab.dataset.tab).classList.add('active');
+ // --- Helpers ---
+ function fmt(n) { return (parseFloat(n) || 0).toFixed(2); }
+ function esc(s) {
+ if (!s) return '';
+ var d = document.createElement('div');
+ d.textContent = s;
+ return d.innerHTML;
+ }
- if (tab.dataset.tab === 'alerts') loadAlerts();
- });
- });
+ // =====================================================================
+ // TAB SWITCHING — uses design-system switchTab() already in the HTML.
+ // We hook into it to trigger data loads when tabs are activated.
+ // =====================================================================
- // --- Products ---
- async function loadItems(page, search) {
+ var _origSwitchTab = window.switchTab;
+ window.switchTab = function (name) {
+ if (typeof _origSwitchTab === 'function') _origSwitchTab(name);
+ if (name === 'alertas') loadAlerts();
+ if (name === 'stock') loadItems(currentPage);
+ };
+
+ // =====================================================================
+ // STOCK / PRODUCTS (panel-stock)
+ // =====================================================================
+
+ function loadItems(page, search) {
currentPage = page || 1;
currentSearch = search !== undefined ? search : currentSearch;
var params = new URLSearchParams({ page: currentPage, per_page: 50 });
if (currentSearch) params.set('q', currentSearch);
- var data = await apiFetch(API + '/items?' + params.toString());
- if (!data) return;
+ apiFetch(API + '/items?' + params.toString()).then(function (data) {
+ if (!data) return;
- var tbody = document.getElementById('productTableBody');
- var items = data.data || [];
- if (!items.length) { tbody.innerHTML = '
| Sin productos |
'; return; }
+ var tbody = document.getElementById('productTableBody');
+ var items = data.data || [];
+ if (!items.length) {
+ tbody.innerHTML = '| Sin productos |
';
+ document.getElementById('productPagination').innerHTML = '';
+ return;
+ }
- tbody.innerHTML = items.map(function (it) {
- return '' +
- '| ' + esc(it.barcode) + ' | ' +
- '' + esc(it.part_number) + ' | ' +
- '' + esc(it.name) + ' | ' +
- '' + esc(it.brand) + ' | ' +
- '' + it.stock + ' | ' +
- '$' + fmt(it.cost) + ' | ' +
- '$' + fmt(it.price_1) + ' | ' +
- '$' + fmt(it.price_2) + ' | ' +
- '$' + fmt(it.price_3) + ' | ' +
- '' + esc(it.location) + ' | ' +
- ' ' +
- ' | ' +
- '
';
- }).join('');
+ tbody.innerHTML = items.map(function (it) {
+ return '' +
+ '| ' + esc(it.barcode) + ' | ' +
+ '' + esc(it.part_number) + ' | ' +
+ '' + esc(it.name) + ' | ' +
+ '' + esc(it.brand) + ' | ' +
+ '' + it.stock + ' | ' +
+ '$' + fmt(it.cost) + ' | ' +
+ '$' + fmt(it.price_1) + ' | ' +
+ '$' + fmt(it.price_2) + ' | ' +
+ '$' + fmt(it.price_3) + ' | ' +
+ '' + esc(it.location) + ' | ' +
+ '' +
+ ' ' +
+ '' +
+ ' |
';
+ }).join('');
- // Pagination
- var pg = data.pagination || {};
- var pgEl = document.getElementById('productPagination');
- if (pg.total_pages > 1) {
- pgEl.innerHTML = '' +
- '' + pg.page + ' / ' + pg.total_pages + ' (' + pg.total + ' items)' +
- '';
- } else {
- pgEl.innerHTML = '' + (pg.total || 0) + ' productos';
- }
+ // Pagination
+ var pg = data.pagination || {};
+ var pgEl = document.getElementById('productPagination');
+ if (pg.total_pages > 1) {
+ pgEl.innerHTML =
+ '';
+ } else {
+ pgEl.innerHTML = '' + (pg.total || 0) + ' productos';
+ }
+ });
}
// Search
var searchInput = document.getElementById('productSearch');
var searchTimeout;
- searchInput.addEventListener('input', function () {
- clearTimeout(searchTimeout);
- searchTimeout = setTimeout(function () { loadItems(1, searchInput.value.trim()); }, 350);
- });
+ if (searchInput) {
+ searchInput.addEventListener('input', function () {
+ clearTimeout(searchTimeout);
+ searchTimeout = setTimeout(function () {
+ loadItems(1, searchInput.value.trim());
+ }, 350);
+ });
+ }
- // --- Create item ---
- async function createItem() {
+ // =====================================================================
+ // CREATE ITEM (createModal)
+ // =====================================================================
+
+ function showCreateModal() {
+ document.getElementById('createModal').classList.add('is-open');
+ }
+ function closeCreateModal() {
+ document.getElementById('createModal').classList.remove('is-open');
+ document.getElementById('createResult').innerHTML = '';
+ }
+
+ function createItem() {
var data = {
part_number: document.getElementById('newPartNumber').value.trim(),
name: document.getElementById('newName').value.trim(),
@@ -98,19 +141,33 @@
initial_stock: parseInt(document.getElementById('newInitialStock').value) || 0,
location: document.getElementById('newLocation').value.trim()
};
- if (!data.part_number || !data.name) { document.getElementById('createResult').innerHTML = 'Numero de parte y nombre son obligatorios'; return; }
-
- var result = await apiFetch(API + '/items', { method: 'POST', body: JSON.stringify(data) });
- if (result && result.id) {
- document.getElementById('createResult').innerHTML = 'Creado ID ' + result.id + ' | Barcode: ' + result.barcode + '';
- loadItems(currentPage);
- } else {
- document.getElementById('createResult').innerHTML = '' + (result ? result.error || 'Error' : 'Error de red') + '';
+ if (!data.part_number || !data.name) {
+ document.getElementById('createResult').innerHTML = 'Numero de parte y nombre son obligatorios';
+ return;
}
+ apiFetch(API + '/items', { method: 'POST', body: JSON.stringify(data) }).then(function (result) {
+ if (result && result.id) {
+ document.getElementById('createResult').innerHTML = 'Creado ID ' + result.id + ' | Barcode: ' + result.barcode + '';
+ loadItems(currentPage);
+ } else {
+ document.getElementById('createResult').innerHTML = '' + (result ? result.error || 'Error' : 'Error de red') + '';
+ }
+ });
}
- // --- Purchase ---
- async function recordPurchase() {
+ // =====================================================================
+ // PURCHASE / ENTRADA (purchaseModal)
+ // =====================================================================
+
+ function showPurchaseModal() {
+ document.getElementById('purchaseModal').classList.add('is-open');
+ }
+ function closePurchaseModal() {
+ document.getElementById('purchaseModal').classList.remove('is-open');
+ document.getElementById('purchaseResult').innerHTML = '';
+ }
+
+ function recordPurchase() {
var data = {
inventory_id: parseInt(document.getElementById('purchaseItemId').value),
quantity: parseInt(document.getElementById('purchaseQty').value),
@@ -119,32 +176,58 @@
notes: document.getElementById('purchaseNotes').value.trim()
};
if (!data.inventory_id || !data.quantity || !data.unit_cost) {
- document.getElementById('purchaseResult').innerHTML = 'Complete todos los campos'; return;
+ document.getElementById('purchaseResult').innerHTML = 'Complete todos los campos obligatorios';
+ return;
}
- var result = await apiFetch(API + '/purchase', { method: 'POST', body: JSON.stringify(data) });
- document.getElementById('purchaseResult').innerHTML = result && result.operation_id
- ? 'Compra registrada (op #' + result.operation_id + ')'
- : '' + (result ? result.error || 'Error' : 'Error de red') + '';
+ apiFetch(API + '/purchase', { method: 'POST', body: JSON.stringify(data) }).then(function (result) {
+ document.getElementById('purchaseResult').innerHTML = result && result.operation_id
+ ? 'Compra registrada (op #' + result.operation_id + ')'
+ : '' + (result ? result.error || 'Error' : 'Error de red') + '';
+ });
}
- // --- Adjustment ---
- async function recordAdjustment() {
+ // =====================================================================
+ // ADJUSTMENT / AJUSTE (adjustmentModal)
+ // =====================================================================
+
+ function showAdjustmentModal() {
+ document.getElementById('adjustmentModal').classList.add('is-open');
+ }
+ function closeAdjustmentModal() {
+ document.getElementById('adjustmentModal').classList.remove('is-open');
+ document.getElementById('adjustResult').innerHTML = '';
+ }
+
+ function recordAdjustment() {
var data = {
inventory_id: parseInt(document.getElementById('adjustItemId').value),
quantity: parseInt(document.getElementById('adjustQty').value),
reason: document.getElementById('adjustReason').value.trim()
};
if (!data.inventory_id || data.quantity === undefined || !data.reason) {
- document.getElementById('adjustResult').innerHTML = 'Complete todos los campos (razon obligatoria)'; return;
+ document.getElementById('adjustResult').innerHTML = 'Complete todos los campos (razon obligatoria)';
+ return;
}
- var result = await apiFetch(API + '/adjustment', { method: 'POST', body: JSON.stringify(data) });
- document.getElementById('adjustResult').innerHTML = result && result.operation_id
- ? 'Ajuste registrado (op #' + result.operation_id + ')'
- : '' + (result ? result.error || 'Error' : 'Error de red') + '';
+ apiFetch(API + '/adjustment', { method: 'POST', body: JSON.stringify(data) }).then(function (result) {
+ document.getElementById('adjustResult').innerHTML = result && result.operation_id
+ ? 'Ajuste registrado (op #' + result.operation_id + ')'
+ : '' + (result ? result.error || 'Error' : 'Error de red') + '';
+ });
}
- // --- Transfer ---
- async function recordTransfer() {
+ // =====================================================================
+ // TRANSFER / TRASPASO (transferModal)
+ // =====================================================================
+
+ function showTransferModal() {
+ document.getElementById('transferModal').classList.add('is-open');
+ }
+ function closeTransferModal() {
+ document.getElementById('transferModal').classList.remove('is-open');
+ document.getElementById('transferResult').innerHTML = '';
+ }
+
+ function recordTransfer() {
var data = {
inventory_id: parseInt(document.getElementById('transferItemId').value),
from_branch_id: parseInt(document.getElementById('transferFrom').value),
@@ -153,27 +236,44 @@
notes: document.getElementById('transferNotes').value.trim()
};
if (!data.inventory_id || !data.from_branch_id || !data.to_branch_id || !data.quantity) {
- document.getElementById('transferResult').innerHTML = 'Complete todos los campos'; return;
+ document.getElementById('transferResult').innerHTML = 'Complete todos los campos';
+ return;
}
- var result = await apiFetch(API + '/transfer', { method: 'POST', body: JSON.stringify(data) });
- document.getElementById('transferResult').innerHTML = result && result.out_operation_id
- ? 'Transferencia registrada'
- : '' + (result ? result.error || 'Error' : 'Error de red') + '';
+ apiFetch(API + '/transfer', { method: 'POST', body: JSON.stringify(data) }).then(function (result) {
+ document.getElementById('transferResult').innerHTML = result && result.out_operation_id
+ ? 'Transferencia registrada'
+ : '' + (result ? result.error || 'Error' : 'Error de red') + '';
+ });
+ }
+
+ // =====================================================================
+ // PHYSICAL COUNT / CONTEO (countModal)
+ // =====================================================================
+
+ function showCountModal() {
+ document.getElementById('countModal').classList.add('is-open');
+ // Pre-add one line if empty
+ if (!document.querySelectorAll('#countLines .count-row').length) {
+ addCountLine();
+ }
+ }
+ function closeCountModal() {
+ document.getElementById('countModal').classList.remove('is-open');
}
- // --- Physical Count (two-phase) ---
function addCountLine() {
var container = document.getElementById('countLines');
var row = document.createElement('div');
row.className = 'count-row';
- row.innerHTML = '' +
- '' +
- '';
+ row.innerHTML =
+ '' +
+ '' +
+ '';
container.appendChild(row);
}
- async function startPhysicalCount() {
- var rows = document.querySelectorAll('.count-row');
+ function startPhysicalCount() {
+ var rows = document.querySelectorAll('#countLines .count-row');
var items = [];
rows.forEach(function (row) {
var invId = parseInt(row.querySelector('.count-inv-id').value);
@@ -182,85 +282,152 @@
});
if (!items.length) { alert('Agregue al menos una linea'); return; }
- var result = await apiFetch(API + '/physical-count/start', { method: 'POST', body: JSON.stringify({ items: items }) });
- if (!result || !result.count_id) {
- document.getElementById('countResults').innerHTML = '' + (result ? result.error || 'Error' : 'Error de red') + '';
- return;
- }
+ apiFetch(API + '/physical-count/start', { method: 'POST', body: JSON.stringify({ items: items }) }).then(function (result) {
+ if (!result || !result.count_id) {
+ document.getElementById('countResults').innerHTML = '' + (result ? result.error || 'Error' : 'Error de red') + '';
+ return;
+ }
- draftCountId = result.count_id;
- var html = 'Borrador #' + result.count_id + ' — ' + result.message + '
';
- html += '| ID | Esperado | Contado | Diferencia |
';
- (result.results || []).forEach(function (r) {
- var color = r.difference === 0 ? '#16a34a' : (r.difference < 0 ? '#dc2626' : '#ca8a04');
- html += '| ' + r.inventory_id + ' | ' + r.expected + ' | ' + r.counted + ' | ' + (r.difference > 0 ? '+' : '') + r.difference + ' |
';
+ draftCountId = result.count_id;
+ var html = 'Borrador #' + result.count_id + ' — ' + esc(result.message) + '
';
+ html += '| ID | Esperado | Contado | Diferencia |
';
+ (result.results || []).forEach(function (r) {
+ var color = r.difference === 0 ? 'var(--color-success)' : (r.difference < 0 ? 'var(--color-error)' : 'var(--color-warning)');
+ html += '| ' + r.inventory_id + ' | ' + r.expected + ' | ' + r.counted + ' | ' + (r.difference > 0 ? '+' : '') + r.difference + ' |
';
+ });
+ html += '
';
+ html += '';
+ html += '';
+ html += '';
+ html += '
';
+ document.getElementById('countResults').innerHTML = html;
});
- html += '
';
- html += '';
- html += ' ';
- document.getElementById('countResults').innerHTML = html;
}
- async function approvePhysicalCount() {
+ function approvePhysicalCount() {
if (!draftCountId) { alert('No hay borrador activo'); return; }
- var result = await apiFetch(API + '/physical-count/approve', { method: 'POST', body: JSON.stringify({ count_id: draftCountId }) });
- if (result && result.status === 'approved') {
- document.getElementById('countResults').innerHTML = '' + result.message + '';
- draftCountId = null;
- } else {
- document.getElementById('countResults').innerHTML += '
' + (result ? result.error || 'Error' : 'Error de red') + '';
- }
+ apiFetch(API + '/physical-count/approve', { method: 'POST', body: JSON.stringify({ count_id: draftCountId }) }).then(function (result) {
+ if (result && result.status === 'approved') {
+ document.getElementById('countResults').innerHTML = '' + esc(result.message) + '';
+ draftCountId = null;
+ } else {
+ document.getElementById('countResults').innerHTML += '
' + (result ? result.error || 'Error' : 'Error de red') + '';
+ }
+ });
}
function cancelDraft() {
draftCountId = null;
- document.getElementById('countResults').innerHTML = 'Borrador cancelado';
+ document.getElementById('countResults').innerHTML = 'Borrador cancelado';
}
- // --- Alerts ---
- async function loadAlerts() {
- var data = await apiFetch(API + '/alerts');
- if (!data) return;
- var el = document.getElementById('alertsList');
- var alerts = data.data || [];
- if (!alerts.length) { el.innerHTML = 'Sin alertas activas
'; return; }
+ // =====================================================================
+ // ALERTS (panel-alertas)
+ // =====================================================================
- el.innerHTML = alerts.map(function (a) {
- var cls = a.severity === 'critical' ? 'alert-critical' : (a.severity === 'warning' ? 'alert-warning' : 'alert-info');
- var icon = a.type === 'zero' ? 'AGOTADO' : (a.type === 'low' ? 'BAJO' : 'EXCESO');
- return '' +
- '
[' + icon + '] ' + esc(a.part_number) + ' — ' + esc(a.name) + ' | Stock: ' + a.stock +
- (a.min_stock ? ' (min: ' + a.min_stock + ')' : '') + (a.max_stock ? ' (max: ' + a.max_stock + ')' : '') + '
' +
- '
Sucursal ' + a.branch_id + ' ';
- }).join('');
+ function loadAlerts() {
+ apiFetch(API + '/alerts').then(function (data) {
+ if (!data) return;
+ var alerts = data.data || [];
+ var container = document.getElementById('alertsContent');
+ if (!container) return;
+
+ if (!alerts.length) {
+ container.innerHTML = 'Sin alertas activas
';
+ return;
+ }
+
+ var html = '';
+
+ // Group by severity
+ var critical = alerts.filter(function (a) { return a.severity === 'critical'; });
+ var warning = alerts.filter(function (a) { return a.severity === 'warning'; });
+ var info = alerts.filter(function (a) { return a.severity !== 'critical' && a.severity !== 'warning'; });
+
+ if (critical.length) {
+ html += 'Criticas' + critical.length + ' ';
+ html += '';
+ critical.forEach(function (a) {
+ var icon = a.type === 'zero' ? 'AGOTADO' : (a.type === 'low' ? 'BAJO' : a.type.toUpperCase());
+ html += buildAlertCard(a, icon, 'critical');
+ });
+ html += '
';
+ }
+
+ if (warning.length) {
+ html += 'Advertencias' + warning.length + ' ';
+ html += '';
+ warning.forEach(function (a) {
+ html += buildAlertCard(a, 'EXCESO', 'warning');
+ });
+ html += '
';
+ }
+
+ if (info.length) {
+ html += 'Informativas' + info.length + ' ';
+ html += '';
+ info.forEach(function (a) {
+ html += buildAlertCard(a, 'INFO', 'info');
+ });
+ html += '
';
+ }
+
+ container.innerHTML = html;
+ });
}
- // --- History modal ---
- async function viewHistory(itemId) {
- var data = await apiFetch(API + '/items/' + itemId + '/history');
- if (!data) return;
- var history = data.data || [];
- var html = '';
- if (!history.length) { html = 'Sin movimientos
'; }
- else {
- html = '| Fecha | Tipo | Cantidad | Costo | Empleado | Notas |
';
- history.forEach(function (h) {
- var qtyColor = h.quantity > 0 ? '#16a34a' : '#dc2626';
- html += '| ' + h.date + ' | ' + h.type + ' | ' + (h.quantity > 0 ? '+' : '') + h.quantity + ' | ' + (h.cost ? '$' + fmt(h.cost) : '-') + ' | ' + esc(h.employee) + ' | ' + esc(h.notes) + ' |
';
- });
- html += '
';
- }
- document.getElementById('historyContent').innerHTML = html;
- document.getElementById('historyModal').classList.add('show');
+ function buildAlertCard(a, icon, level) {
+ var cls = level === 'critical' ? 'alert-card--critical' : (level === 'warning' ? 'alert-card--warning' : 'alert-card--info');
+ return '' +
+ '
' +
+ '
' +
+ '
[' + icon + '] ' + esc(a.part_number) + ' — ' + esc(a.name) + '
' +
+ '
Stock: ' + a.stock +
+ (a.min_stock ? ' (min: ' + a.min_stock + ')' : '') +
+ (a.max_stock ? ' (max: ' + a.max_stock + ')' : '') +
+ ' · Sucursal ' + a.branch_id + '
' +
+ '
';
}
- function closeHistoryModal() { document.getElementById('historyModal').classList.remove('show'); }
+ // =====================================================================
+ // HISTORY MODAL
+ // =====================================================================
- // --- Create modal ---
- function showCreateModal() { document.getElementById('createModal').classList.add('show'); }
- function closeCreateModal() { document.getElementById('createModal').classList.remove('show'); }
+ function viewHistory(itemId) {
+ apiFetch(API + '/items/' + itemId + '/history').then(function (data) {
+ if (!data) return;
+ var history = data.data || [];
+ var html = '';
+ if (!history.length) {
+ html = 'Sin movimientos
';
+ } else {
+ html = '| Fecha | Tipo | Cantidad | Costo | Empleado | Notas |
';
+ history.forEach(function (h) {
+ var qtyColor = h.quantity > 0 ? 'var(--color-success)' : 'var(--color-error)';
+ html += '' +
+ '| ' + esc(h.date) + ' | ' +
+ '' + esc(h.type) + ' | ' +
+ '' + (h.quantity > 0 ? '+' : '') + h.quantity + ' | ' +
+ '' + (h.cost ? '$' + fmt(h.cost) : '—') + ' | ' +
+ '' + esc(h.employee) + ' | ' +
+ '' + esc(h.notes) + ' | ' +
+ '
';
+ });
+ html += '
';
+ }
+ document.getElementById('historyContent').innerHTML = html;
+ document.getElementById('historyModal').classList.add('is-open');
+ });
+ }
+
+ function closeHistoryModal() {
+ document.getElementById('historyModal').classList.remove('is-open');
+ }
+
+ // =====================================================================
+ // BARCODE LABEL PRINT
+ // =====================================================================
- // --- Barcode label ---
function printBarcode(barcode, partNumber, name) {
var w = window.open('', '_blank', 'width=400,height=250');
w.document.write('Etiqueta');
@@ -272,20 +439,27 @@
w.print();
}
- // --- Helpers ---
- function fmt(n) { return (parseFloat(n) || 0).toFixed(2); }
- function esc(s) { if (!s) return ''; var d = document.createElement('div'); d.textContent = s; return d.innerHTML; }
+ // =====================================================================
+ // EXPOSE GLOBALS (for onclick handlers in HTML)
+ // =====================================================================
- // --- Expose globals ---
window._loadItems = function (p) { loadItems(p); };
window.viewHistory = viewHistory;
window.closeHistoryModal = closeHistoryModal;
window.showCreateModal = showCreateModal;
window.closeCreateModal = closeCreateModal;
window.createItem = createItem;
+ window.showPurchaseModal = showPurchaseModal;
+ window.closePurchaseModal = closePurchaseModal;
window.recordPurchase = recordPurchase;
+ window.showAdjustmentModal = showAdjustmentModal;
+ window.closeAdjustmentModal = closeAdjustmentModal;
window.recordAdjustment = recordAdjustment;
+ window.showTransferModal = showTransferModal;
+ window.closeTransferModal = closeTransferModal;
window.recordTransfer = recordTransfer;
+ window.showCountModal = showCountModal;
+ window.closeCountModal = closeCountModal;
window.addCountLine = addCountLine;
window.startPhysicalCount = startPhysicalCount;
window.approvePhysicalCount = approvePhysicalCount;
@@ -293,6 +467,9 @@
window.loadAlerts = loadAlerts;
window.printBarcode = printBarcode;
- // --- Init ---
+ // =====================================================================
+ // INIT — load stock on page load
+ // =====================================================================
+
loadItems(1);
})();
diff --git a/pos/templates/inventory.html b/pos/templates/inventory.html
index 3e5270a..413e50b 100644
--- a/pos/templates/inventory.html
+++ b/pos/templates/inventory.html
@@ -1172,6 +1172,141 @@
padding: var(--space-1); opacity: 0.7; color: inherit;
}
.banner__dismiss:hover { opacity: 1; }
+
+ /* =========================================================================
+ INVENTORY MODALS
+ ========================================================================= */
+
+ .inv-modal-overlay {
+ display: none;
+ position: fixed;
+ inset: 0;
+ z-index: 9000;
+ background: rgba(0,0,0,0.6);
+ backdrop-filter: blur(4px);
+ align-items: center;
+ justify-content: center;
+ }
+
+ .inv-modal-overlay.is-open {
+ display: flex;
+ }
+
+ .inv-modal {
+ background: var(--color-bg-elevated);
+ border: 1px solid var(--color-border);
+ border-radius: var(--radius-lg);
+ width: 520px;
+ max-height: 85vh;
+ overflow-y: auto;
+ box-shadow: 0 20px 60px rgba(0,0,0,0.4);
+ }
+
+ .inv-modal--wide {
+ width: 700px;
+ }
+
+ .inv-modal__header {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: var(--space-4) var(--space-5);
+ border-bottom: 1px solid var(--color-border);
+ }
+
+ .inv-modal__header h3 {
+ font-family: var(--font-heading);
+ font-weight: var(--heading-weight-primary);
+ font-size: var(--text-h5);
+ color: var(--color-text-primary);
+ margin: 0;
+ }
+
+ .inv-modal__close {
+ background: none;
+ border: none;
+ font-size: 1.5rem;
+ color: var(--color-text-muted);
+ cursor: pointer;
+ padding: 0 var(--space-1);
+ line-height: 1;
+ }
+
+ .inv-modal__close:hover {
+ color: var(--color-text-primary);
+ }
+
+ .inv-modal__body {
+ padding: var(--space-4) var(--space-5);
+ }
+
+ .inv-modal__footer {
+ display: flex;
+ justify-content: flex-end;
+ gap: var(--space-3);
+ padding: var(--space-3) var(--space-5);
+ border-top: 1px solid var(--color-border);
+ }
+
+ .inv-form-grid {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ gap: var(--space-3);
+ }
+
+ .inv-field {
+ display: flex;
+ flex-direction: column;
+ gap: var(--space-1);
+ }
+
+ .inv-field--full {
+ grid-column: 1 / -1;
+ }
+
+ .inv-field label {
+ font-size: var(--text-caption);
+ font-weight: var(--font-weight-semibold);
+ color: var(--color-text-muted);
+ letter-spacing: var(--tracking-wide);
+ text-transform: uppercase;
+ }
+
+ .inv-field input {
+ padding: var(--space-2) var(--space-3);
+ background: var(--color-surface-1);
+ border: 1px solid var(--color-border);
+ border-radius: var(--radius-md);
+ color: var(--color-text-primary);
+ font-family: var(--font-body);
+ font-size: var(--text-body-sm);
+ }
+
+ .inv-field input:focus {
+ outline: none;
+ border-color: var(--color-primary);
+ box-shadow: 0 0 0 2px var(--color-primary-muted);
+ }
+
+ .count-row {
+ display: flex;
+ gap: var(--space-2);
+ align-items: center;
+ margin-bottom: var(--space-2);
+ }
+
+ .count-row input {
+ padding: var(--space-2) var(--space-3);
+ background: var(--color-surface-1);
+ border: 1px solid var(--color-border);
+ border-radius: var(--radius-md);
+ color: var(--color-text-primary);
+ font-family: var(--font-body);
+ font-size: var(--text-body-sm);
+ }
+
+ /* History table inside modal */
+ .inv-modal .data-table { width: 100%; }
@@ -1430,7 +1565,7 @@
-
+
- | SKU |
- Nombre del Producto |
+ Barcode |
+ No. Parte |
+ Nombre |
Marca |
- Categoría |
Stock |
- Mín |
- Máx |
+ Costo |
+ Precio 1 |
+ Precio 2 |
+ Precio 3 |
Ubicación |
- Estado |
+ Acciones |
-
-
- | GAT-50104 |
- Banda de Tiempo Kit |
- Gates |
- Motor |
- 142 |
- 20 |
- 200 |
- A-12-3 |
- OK |
-
-
- | SKF-6204 |
- Rodamiento Rueda Delantera |
- SKF |
- Suspensión |
- 8 |
- 15 |
- 60 |
- B-05-1 |
- Bajo |
-
-
- | BOC-0258 |
- Bujía Iridium BKR6EIX |
- Bosch |
- Eléctrico |
- 3 |
- 10 |
- 100 |
- C-08-2 |
- Bajo |
-
-
- | MON-G8114 |
- Amortiguador Trasero Derecho |
- Monroe |
- Suspensión |
- 67 |
- 10 |
- 40 |
- B-14-5 |
- Sobrestock |
-
-
- | NGK-LFR6A |
- Bujía Laser Platinum LFR6A |
- NGK |
- Eléctrico |
- 88 |
- 25 |
- 120 |
- C-02-4 |
- OK |
-
-
- | BOC-F026 |
- Filtro de Aceite F026407006 |
- Bosch |
- Filtros |
- 5 |
- 20 |
- 80 |
- D-01-2 |
- Bajo |
-
-
- | ATE-13046 |
- Pastillas de Freno ATE Power |
- ATE |
- Frenos |
- 34 |
- 15 |
- 50 |
- E-03-1 |
- OK |
-
-
- | TRW-GDB1 |
- Disco de Freno Ventilado |
- TRW |
- Frenos |
- 12 |
- 10 |
- 30 |
- E-07-3 |
- OK |
-
+
@@ -1594,7 +1638,7 @@
-