diff --git a/pos/static/js/inventory.js b/pos/static/js/inventory.js index d977bce..4d78501 100644 --- a/pos/static/js/inventory.js +++ b/pos/static/js/inventory.js @@ -6,10 +6,10 @@ 'use strict'; var API = '/pos/api/inventory'; - var token = localStorage.getItem('pos_token'); - if (!token) { window.location.href = '/pos/login'; return; } + function getToken() { return localStorage.getItem('pos_token') || ''; } + if (!getToken()) { window.location.href = '/pos/login'; return; } - var headers = { 'Authorization': 'Bearer ' + token, 'Content-Type': 'application/json' }; + function authHeaders() { return { 'Authorization': 'Bearer ' + getToken(), 'Content-Type': 'application/json' }; } var currentPage = 1; var currentSearch = ''; var draftCountId = null; @@ -37,7 +37,7 @@ // Load compatibility source setting (function loadCompatSource() { - fetch('/pos/api/config/vehicle-compat-source', { headers: { 'Authorization': 'Bearer ' + token } }) + fetch('/pos/api/config/vehicle-compat-source', { headers: { 'Authorization': 'Bearer ' + getToken() } }) .then(function(r) { return r.json(); }) .then(function(d) { if (d.source) compatSource = d.source; @@ -46,7 +46,7 @@ // --- API helper --- function apiFetch(url, opts) { - return fetch(url, Object.assign({ headers: headers }, opts || {})) + return fetch(url, Object.assign({ headers: authHeaders() }, opts || {})) .then(function (resp) { if (resp.status === 401) { localStorage.removeItem('pos_token'); @@ -128,7 +128,7 @@ var d3 = parseFloat(document.getElementById('tierDisc3').value) || 0; fetch(API + '/tier-discounts', { method: 'PUT', - headers: { 'Authorization': 'Bearer ' + token, 'Content-Type': 'application/json' }, + headers: { 'Authorization': 'Bearer ' + getToken(), 'Content-Type': 'application/json' }, body: JSON.stringify({ discount_pct_2: d2, discount_pct_3: d3 }) }).then(function(r) { return r.json(); }) .then(function(res) { @@ -527,7 +527,7 @@ fetch(API + '/items/bulk-import', { method: 'POST', headers: { - 'Authorization': 'Bearer ' + token, + 'Authorization': 'Bearer ' + getToken(), 'X-Import-Mode': mode, 'X-Import-Strategy': strategy }, @@ -1134,10 +1134,9 @@ function deleteItem(itemId) { if (!confirm('¿Eliminar este artículo del inventario? Se mantendrán los registros históricos.')) return; - var token = localStorage.getItem('pos_token') || ''; fetch(API + '/items/' + itemId, { method: 'DELETE', - headers: token ? { 'Authorization': 'Bearer ' + token } : {} + headers: getToken() ? { 'Authorization': 'Bearer ' + getToken() } : {} }).then(function(r) { return r.json(); }) .then(function(data) { if (data.error) { showToast(data.error, 'error', { title: 'Error al eliminar' }); return; } @@ -1190,7 +1189,7 @@ var ids = Array.from(selectedItems); fetch('/pos/api/marketplace-ext/inventory-check', { method: 'POST', - headers: { 'Authorization': 'Bearer ' + token, 'Content-Type': 'application/json' }, + headers: { 'Authorization': 'Bearer ' + getToken(), 'Content-Type': 'application/json' }, body: JSON.stringify({ inventory_ids: ids }) }).then(function(r){ return r.json(); }) .then(function(data) { @@ -1245,7 +1244,7 @@ formData.append('file', file); fetch('/pos/api/inventory/items/' + itemId + '/image', { method: 'POST', - headers: { 'Authorization': 'Bearer ' + token }, + headers: { 'Authorization': 'Bearer ' + getToken() }, body: formData }).then(function(r){ return r.json(); }) .then(function(data) { @@ -1270,7 +1269,7 @@ clearTimeout(meliCategorySearchTimeout); resultsDiv.innerHTML = '
Buscando...
'; meliCategorySearchTimeout = setTimeout(function() { - fetch('/pos/api/marketplace-ext/categories?q=' + encodeURIComponent(q), { headers: { 'Authorization': 'Bearer ' + token, 'Content-Type': 'application/json' } }) + fetch('/pos/api/marketplace-ext/categories?q=' + encodeURIComponent(q), { headers: { 'Authorization': 'Bearer ' + getToken(), 'Content-Type': 'application/json' } }) .then(function(r) { return r.json(); }) .then(function(data) { var cats = data.categories || []; @@ -1317,7 +1316,7 @@ var section = document.getElementById('meliAttrsSection'); grid.innerHTML = '

Cargando atributos...

'; section.style.display = 'block'; - fetch('/pos/api/marketplace-ext/categories/' + encodeURIComponent(categoryId) + '/attributes', { headers: { 'Authorization': 'Bearer ' + token } }) + fetch('/pos/api/marketplace-ext/categories/' + encodeURIComponent(categoryId) + '/attributes', { headers: { 'Authorization': 'Bearer ' + getToken() } }) .then(function(r){ return r.json(); }) .then(function(data) { meliCategoryAttrs = data.attributes || []; @@ -1446,7 +1445,7 @@ resultEl.innerHTML = 'Validando con MercadoLibre...'; fetch('/pos/api/marketplace-ext/listings/validate', { method: 'POST', - headers: { 'Authorization': 'Bearer ' + token, 'Content-Type': 'application/json' }, + headers: { 'Authorization': 'Bearer ' + getToken(), 'Content-Type': 'application/json' }, body: JSON.stringify({ inventory_ids: ids, category_id: categoryId, @@ -1536,7 +1535,7 @@ var maxAttempts = 60; // 2 min var interval = setInterval(function() { attempts++; - fetch('/pos/api/marketplace-ext/listings/async/' + encodeURIComponent(taskId), { headers: { 'Authorization': 'Bearer ' + token } }) + fetch('/pos/api/marketplace-ext/listings/async/' + encodeURIComponent(taskId), { headers: { 'Authorization': 'Bearer ' + getToken() } }) .then(function(r){ return r.json(); }) .then(function(data) { if (data.status === 'done') { @@ -1573,7 +1572,7 @@ resultEl.innerHTML = '' + (useAsync ? 'Encolando ' : 'Publicando ') + ids.length + ' producto(s)...'; fetch(endpoint, { method: 'POST', - headers: { 'Authorization': 'Bearer ' + token, 'Content-Type': 'application/json' }, + headers: { 'Authorization': 'Bearer ' + getToken(), 'Content-Type': 'application/json' }, body: JSON.stringify({ inventory_ids: ids, category_id: categoryId, @@ -1632,7 +1631,7 @@ if (statusEl) statusEl.textContent = 'Subiendo...'; fetch(API + '/items/' + itemId + '/image', { method: 'POST', - headers: { 'Authorization': 'Bearer ' + token }, + headers: { 'Authorization': 'Bearer ' + getToken() }, body: fd }) .then(function (r) { return r.json(); }) @@ -1655,7 +1654,7 @@ if (!confirm('Eliminar imagen de este producto?')) return; fetch(API + '/items/' + itemId + '/image', { method: 'DELETE', - headers: { 'Authorization': 'Bearer ' + token } + headers: { 'Authorization': 'Bearer ' + getToken() } }) .then(function (r) { return r.json(); }) .then(function (result) { @@ -1765,7 +1764,7 @@ ? '/pos/api/catalog/part/' + catalogPartId : '/pos/api/catalog/search?q=' + encodeURIComponent(partNumber); - fetch(url, { headers: { 'Authorization': 'Bearer ' + token } }) + fetch(url, { headers: { 'Authorization': 'Bearer ' + getToken() } }) .then(function(r) { return r.json(); }) .then(function(d) { var el = document.getElementById('crossRefContent'); @@ -1777,7 +1776,7 @@ // If it was a search, get alternatives from first result if (!catalogPartId && d.data && d.data.length > 0) { // Fetch detail for first match - fetch('/pos/api/catalog/part/' + d.data[0].id_part, { headers: { 'Authorization': 'Bearer ' + token } }) + fetch('/pos/api/catalog/part/' + d.data[0].id_part, { headers: { 'Authorization': 'Bearer ' + getToken() } }) .then(function(r2) { return r2.json(); }) .then(function(d2) { renderCrossRefs(el, d2.alternatives || [], d2.bodegas || []); @@ -1850,7 +1849,7 @@ // Load SKU aliases (function loadSkuAliases() { - fetch('/pos/api/inventory/items/' + itemId + '/skus', { headers: { 'Authorization': 'Bearer ' + token } }) + fetch('/pos/api/inventory/items/' + itemId + '/skus', { headers: { 'Authorization': 'Bearer ' + getToken() } }) .then(function(r) { return r.json(); }) .then(function(d) { var el = document.getElementById('skuAliasContent'); @@ -1882,7 +1881,7 @@ // Load vehicle compatibilities and makes (function loadCompatPanel() { - fetch('/pos/api/inventory/items/' + itemId + '/vehicles', { headers: { 'Authorization': 'Bearer ' + token } }) + fetch('/pos/api/inventory/items/' + itemId + '/vehicles', { headers: { 'Authorization': 'Bearer ' + getToken() } }) .then(function(r) { return r.json(); }) .then(function(d) { var el = document.getElementById('compatContent'); @@ -1908,7 +1907,7 @@ }); // Load makes - fetch('/pos/api/inventory/vehicles/makes', { headers: { 'Authorization': 'Bearer ' + token } }) + fetch('/pos/api/inventory/vehicles/makes', { headers: { 'Authorization': 'Bearer ' + getToken() } }) .then(function(r) { return r.json(); }) .then(function(d) { var sel = document.getElementById('manualMake'); @@ -1952,7 +1951,7 @@ function autoMatchCompat(itemId) { fetch('/pos/api/inventory/items/' + itemId + '/vehicles/auto-match', { method: 'POST', - headers: { 'Authorization': 'Bearer ' + token } + headers: { 'Authorization': 'Bearer ' + getToken() } }).then(function(r) { return r.json(); }) .then(function(d) { var msg = ''; @@ -1975,7 +1974,7 @@ if (!confirm('Quitar compatibilidad con este vehiculo?')) return; fetch('/pos/api/inventory/items/' + itemId + '/vehicles/' + compatId, { method: 'DELETE', - headers: { 'Authorization': 'Bearer ' + token } + headers: { 'Authorization': 'Bearer ' + getToken() } }).then(function(r) { return r.json(); }) .then(function() { viewProductDetail(itemId); @@ -2008,7 +2007,7 @@ modelSel.innerHTML = ''; return; } - fetch('/pos/api/inventory/vehicles/models?brand_id=' + brandId, { headers: { 'Authorization': 'Bearer ' + token } }) + fetch('/pos/api/inventory/vehicles/models?brand_id=' + brandId, { headers: { 'Authorization': 'Bearer ' + getToken() } }) .then(function(r) { return r.json(); }) .then(function(d) { var opts = ''; @@ -2034,7 +2033,7 @@ yearSel.innerHTML = ''; return; } - fetch('/pos/api/inventory/vehicles/years?model_id=' + modelId, { headers: { 'Authorization': 'Bearer ' + token } }) + fetch('/pos/api/inventory/vehicles/years?model_id=' + modelId, { headers: { 'Authorization': 'Bearer ' + getToken() } }) .then(function(r) { return r.json(); }) .then(function(d) { var opts = ''; @@ -2060,7 +2059,7 @@ engineSel.innerHTML = ''; return; } - fetch('/pos/api/inventory/vehicles/engines?model_id=' + modelId + '&year_id=' + yearId, { headers: { 'Authorization': 'Bearer ' + token } }) + fetch('/pos/api/inventory/vehicles/engines?model_id=' + modelId + '&year_id=' + yearId, { headers: { 'Authorization': 'Bearer ' + getToken() } }) .then(function(r) { return r.json(); }) .then(function(d) { var opts = ''; @@ -2088,7 +2087,7 @@ } fetch('/pos/api/inventory/items/' + itemId + '/vehicles/manual', { method: 'POST', - headers: { 'Authorization': 'Bearer ' + token, 'Content-Type': 'application/json' }, + headers: { 'Authorization': 'Bearer ' + getToken(), 'Content-Type': 'application/json' }, body: JSON.stringify({ make: make, model: model, year: parseInt(year), engine: engine, engine_code: engineCode }) }).then(function(r) { return r.json(); }) .then(function(d) { @@ -2106,7 +2105,7 @@ if (!sku) { alert('Ingresa un SKU'); return; } fetch('/pos/api/inventory/items/' + itemId + '/skus', { method: 'POST', - headers: { 'Authorization': 'Bearer ' + token, 'Content-Type': 'application/json' }, + headers: { 'Authorization': 'Bearer ' + getToken(), 'Content-Type': 'application/json' }, body: JSON.stringify({ sku: sku, label: label }) }).then(function(r) { return r.json(); }) .then(function(d) { @@ -2119,7 +2118,7 @@ if (!confirm('Eliminar este SKU alternativo?')) return; fetch('/pos/api/inventory/items/' + itemId + '/skus/' + aliasId, { method: 'DELETE', - headers: { 'Authorization': 'Bearer ' + token } + headers: { 'Authorization': 'Bearer ' + getToken() } }).then(function(r) { return r.json(); }) .then(function() { viewProductDetail(itemId); diff --git a/pos/templates/inventory.html b/pos/templates/inventory.html index 93a1ab9..bbfebd3 100644 --- a/pos/templates/inventory.html +++ b/pos/templates/inventory.html @@ -1067,7 +1067,7 @@ - +