diff --git a/pos/blueprints/catalog_bp.py b/pos/blueprints/catalog_bp.py index 34ecbf1..28b23a0 100644 --- a/pos/blueprints/catalog_bp.py +++ b/pos/blueprints/catalog_bp.py @@ -337,9 +337,8 @@ def parts(): @catalog_bp.route('/part/', methods=['GET']) @require_auth('catalog.view') def part_detail(part_id): - blocked = _oem_blocked() - if blocked: - return blocked + # Part detail is available in both local and OEM modes + # — it reads from the master parts DB and enriches with local stock. def _do(master, tenant, branch_id): result = catalog_service.get_part_detail(master, part_id, tenant, branch_id) if not result: @@ -351,9 +350,8 @@ def part_detail(part_id): @catalog_bp.route('/search', methods=['GET']) @require_auth('catalog.view') def search(): - blocked = _oem_blocked() - if blocked: - return blocked + # Search is available in both local and OEM modes + # — it reads from the master parts DB and enriches with local stock. q = request.args.get('q', '').strip() if not q or len(q) < 2: return jsonify({'data': []}) diff --git a/pos/static/js/inventory.js b/pos/static/js/inventory.js index a011955..3e04a0c 100644 --- a/pos/static/js/inventory.js +++ b/pos/static/js/inventory.js @@ -200,7 +200,11 @@ } 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 + ''; + var msg = 'Creado ID ' + result.id + ' | Barcode: ' + result.barcode; + if (result.vehicle_compatibilities_added > 0) { + msg += ' | ' + result.vehicle_compatibilities_added + ' vehiculo(s) asignado(s) por IA'; + } + document.getElementById('createResult').innerHTML = '' + msg + ''; loadItems(currentPage); } else { document.getElementById('createResult').innerHTML = '' + (result ? result.error || 'Error' : 'Error de red') + ''; @@ -683,7 +687,8 @@ if (list.length > 0) { html2 += ''; list.forEach(function(c) { - html2 += ''; + var sourceLabel = c.source === 'qwen_ai' ? 'IA' : (c.source === 'auto_match' ? 'TecDoc' : esc(c.source || '')); + html2 += ''; html2 += ''; }); html2 += '
MarcaModeloAnoMotorOrigen
' + esc(c.brand || '') + '' + esc(c.model || '') + '' + esc(c.year || '') + '' + esc(c.engine || '') + '' + esc(c.source || '') + '
' + esc(c.brand || '') + '' + esc(c.model || '') + '' + esc(c.year || '') + '' + esc(c.engine || '') + '' + sourceLabel + '
'; @@ -777,6 +782,8 @@ window.cancelDraft = cancelDraft; window.loadAlerts = loadAlerts; window.printBarcode = printBarcode; + window.autoMatchCompat = autoMatchCompat; + window.removeCompat = removeCompat; // ===================================================================== // INIT — load stock on page load diff --git a/pos/static/js/inventory.min.js b/pos/static/js/inventory.min.js index 1f7d01a..3ef7ffc 100644 --- a/pos/static/js/inventory.min.js +++ b/pos/static/js/inventory.min.js @@ -1 +1 @@ -!function(){"use strict";var t="/pos/api/inventory",e=localStorage.getItem("pos_token");if(e){var o={Authorization:"Bearer "+e,"Content-Type":"application/json"},n=1,a="",r=null,i=null,s=window.switchTab;window.switchTab=function(t){"function"==typeof s&&s(t),"alertas"===t&&g(),"stock"===t&&v(n)};var d,c=document.getElementById("productSearch");c&&c.addEventListener("input",(function(){clearTimeout(d),d=setTimeout((function(){v(1,c.value.trim())}),350)})),window._loadItems=function(t){v(t)},window.loadItems=function(t,e){v(t,e)},window.viewHistory=function(e){l(t+"/items/"+e+"/history").then((function(t){if(t){var e=t.data||[],o="";e.length?(o='',e.forEach((function(t){var e=t.quantity>0?"var(--color-success)":"var(--color-error)";o+='"})),o+="
FechaTipoCantidadCostoEmpleadoNotas
'+m(t.date)+""+m(t.type)+''+(t.quantity>0?"+":"")+t.quantity+''+(t.cost?"$"+u(t.cost):"—")+""+m(t.employee)+''+m(t.notes)+"
"):o='

Sin movimientos

',document.getElementById("historyContent").innerHTML=o,document.getElementById("historyModal").classList.add("is-open")}}))},window.viewProductDetail=f,window.uploadItemImage=function(o){var n=document.createElement("input");n.type="file",n.accept="image/jpeg,image/png,image/webp",n.onchange=function(){if(n.files&&n.files[0]){var a=n.files[0];if(a.size>5242880)alert("Imagen demasiado grande (max 5 MB)");else{var r=new FormData;r.append("file",a);var i=document.getElementById("imgUploadStatus");i&&(i.textContent="Subiendo..."),fetch(t+"/items/"+o+"/image",{method:"POST",headers:{Authorization:"Bearer "+e},body:r}).then((function(t){return t.json()})).then((function(t){t.image_url?f(o):i&&(i.textContent=t.error||"Error")})).catch((function(){i&&(i.textContent="Error de red")}))}}},n.click()},window.deleteItemImage=function(o){confirm("Eliminar imagen de este producto?")&&fetch(t+"/items/"+o+"/image",{method:"DELETE",headers:{Authorization:"Bearer "+e}}).then((function(t){return t.json()})).then((function(t){t.message?f(o):alert(t.error||"Error")})).catch((function(){alert("Error de red")}))},window.closeHistoryModal=function(){document.getElementById("historyModal").classList.remove("is-open")},window.showCreateModal=function(){document.getElementById("createModal").classList.add("is-open");var e=document.getElementById("newPartNumber");e&&!e._classifyBound&&(e._classifyBound=!0,e.addEventListener("blur",(function(){var e=this.value.trim();if(!(e.length<3)){var o,n,a=document.getElementById("newName");if(!a||!a.value.trim())o=e,(n=document.getElementById("createResult")).innerHTML='Consultando IA...',l(t+"/classify/"+encodeURIComponent(o)).then((function(t){if(t){t.name&&(document.getElementById("newName").value=t.name),t.brand&&(document.getElementById("newBrand").value=t.brand);var e=[];t.name&&e.push(t.name),t.brand&&e.push(t.brand),t.vehicle&&e.push(t.vehicle),t.category&&e.push(t.category),e.length>0?n.innerHTML='Sugerido por IA: '+m(e.join(" | "))+"":n.innerHTML='IA no pudo identificar este numero de parte'}})).catch((function(){n.innerHTML=""}))}})))},window.closeCreateModal=function(){document.getElementById("createModal").classList.remove("is-open"),document.getElementById("createResult").innerHTML=""},window.createItem=function(){var e={part_number:document.getElementById("newPartNumber").value.trim(),name:document.getElementById("newName").value.trim(),brand:document.getElementById("newBrand").value.trim(),barcode:document.getElementById("newBarcode").value.trim()||void 0,cost:parseFloat(document.getElementById("newCost").value)||0,price_1:parseFloat(document.getElementById("newPrice1").value)||0,price_2:parseFloat(document.getElementById("newPrice2").value)||0,price_3:parseFloat(document.getElementById("newPrice3").value)||0,min_stock:parseInt(document.getElementById("newMinStock").value)||0,initial_stock:parseInt(document.getElementById("newInitialStock").value)||0,location:document.getElementById("newLocation").value.trim()};e.part_number&&e.name?l(t+"/items",{method:"POST",body:JSON.stringify(e)}).then((function(t){t&&t.id?(document.getElementById("createResult").innerHTML='Creado ID '+t.id+" | Barcode: "+t.barcode+"",v(n)):document.getElementById("createResult").innerHTML=''+(t?t.error||"Error":"Error de red")+""})):document.getElementById("createResult").innerHTML='Numero de parte y nombre son obligatorios'},window.showPurchaseModal=function(){document.getElementById("purchaseModal").classList.add("is-open")},window.closePurchaseModal=function(){document.getElementById("purchaseModal").classList.remove("is-open"),document.getElementById("purchaseResult").innerHTML=""},window.recordPurchase=function(){var e={inventory_id:parseInt(document.getElementById("purchaseItemId").value),quantity:parseInt(document.getElementById("purchaseQty").value),unit_cost:parseFloat(document.getElementById("purchaseCost").value),supplier_invoice:document.getElementById("purchaseInvoice").value.trim(),notes:document.getElementById("purchaseNotes").value.trim()};e.inventory_id&&e.quantity&&e.unit_cost?l(t+"/purchase",{method:"POST",body:JSON.stringify(e)}).then((function(t){document.getElementById("purchaseResult").innerHTML=t&&t.operation_id?'Compra registrada (op #'+t.operation_id+")":''+(t?t.error||"Error":"Error de red")+""})):document.getElementById("purchaseResult").innerHTML='Complete todos los campos obligatorios'},window.showAdjustmentModal=function(){document.getElementById("adjustmentModal").classList.add("is-open")},window.closeAdjustmentModal=function(){document.getElementById("adjustmentModal").classList.remove("is-open"),document.getElementById("adjustResult").innerHTML=""},window.recordAdjustment=function(){var e={inventory_id:parseInt(document.getElementById("adjustItemId").value),quantity:parseInt(document.getElementById("adjustQty").value),reason:document.getElementById("adjustReason").value.trim()};e.inventory_id&&void 0!==e.quantity&&e.reason?l(t+"/adjustment",{method:"POST",body:JSON.stringify(e)}).then((function(t){document.getElementById("adjustResult").innerHTML=t&&t.operation_id?'Ajuste registrado (op #'+t.operation_id+")":''+(t?t.error||"Error":"Error de red")+""})):document.getElementById("adjustResult").innerHTML='Complete todos los campos (razon obligatoria)'},window.showTransferModal=function(){document.getElementById("transferModal").classList.add("is-open")},window.closeTransferModal=function(){document.getElementById("transferModal").classList.remove("is-open"),document.getElementById("transferResult").innerHTML=""},window.recordTransfer=function(){var e={inventory_id:parseInt(document.getElementById("transferItemId").value),from_branch_id:parseInt(document.getElementById("transferFrom").value),to_branch_id:parseInt(document.getElementById("transferTo").value),quantity:parseInt(document.getElementById("transferQty").value),notes:document.getElementById("transferNotes").value.trim()};e.inventory_id&&e.from_branch_id&&e.to_branch_id&&e.quantity?l(t+"/transfer",{method:"POST",body:JSON.stringify(e)}).then((function(t){document.getElementById("transferResult").innerHTML=t&&t.out_operation_id?'Transferencia registrada':''+(t?t.error||"Error":"Error de red")+""})):document.getElementById("transferResult").innerHTML='Complete todos los campos'},window.showCountModal=function(){document.getElementById("countModal").classList.add("is-open"),document.querySelectorAll("#countLines .count-row").length||y()},window.closeCountModal=function(){document.getElementById("countModal").classList.remove("is-open")},window.addCountLine=y,window.startPhysicalCount=function(){var e=document.querySelectorAll("#countLines .count-row"),o=[];e.forEach((function(t){var e=parseInt(t.querySelector(".count-inv-id").value),n=parseInt(t.querySelector(".count-qty").value);e&&!isNaN(n)&&o.push({inventory_id:e,counted_quantity:n})})),o.length?l(t+"/physical-count/start",{method:"POST",body:JSON.stringify({items:o})}).then((function(t){if(t&&t.count_id){r=t.count_id;var e='

Borrador #'+t.count_id+" — "+m(t.message)+"

";e+='',(t.results||[]).forEach((function(t){var o=0===t.difference?"var(--color-success)":t.difference<0?"var(--color-error)":"var(--color-warning)";e+=""})),e+="
IDEsperadoContadoDiferencia
"+t.inventory_id+""+t.expected+""+t.counted+''+(t.difference>0?"+":"")+t.difference+"
",e+='
',e+='',e+='',e+="
",document.getElementById("countResults").innerHTML=e}else document.getElementById("countResults").innerHTML=''+(t?t.error||"Error":"Error de red")+""})):alert("Agregue al menos una linea")},window.approvePhysicalCount=function(){r?l(t+"/physical-count/approve",{method:"POST",body:JSON.stringify({count_id:r})}).then((function(t){t&&"approved"===t.status?(document.getElementById("countResults").innerHTML=''+m(t.message)+"",r=null):document.getElementById("countResults").innerHTML+='
'+(t?t.error||"Error":"Error de red")+""})):alert("No hay borrador activo")},window.cancelDraft=function(){r=null,document.getElementById("countResults").innerHTML='Borrador cancelado'},window.loadAlerts=g,window.printBarcode=function(t,e,o){var n=window.open("","_blank","width=400,height=250");n.document.write("Etiqueta"),n.document.write("

"+t+"

"),n.document.write("

"+e+"

"),n.document.write('

'+o+"

"),n.document.write(""),n.document.close(),n.print()},v(1)}else window.location.href="/pos/login";function l(t,e){return fetch(t,Object.assign({headers:o},e||{})).then((function(t){return 401===t.status?(localStorage.removeItem("pos_token"),window.location.href="/pos/login",null):t.json()}))}function u(t){return(parseFloat(t)||0).toFixed(2)}function m(t){if(!t)return"";var e=document.createElement("div");return e.textContent=t,e.innerHTML}function p(t){return''+m(t.barcode)+''+m(t.part_number)+''+m(t.name)+""+m(t.brand)+''+t.stock+'$'+u(t.cost)+'$'+u(t.price_1)+'$'+u(t.price_2)+'$'+u(t.price_3)+""+m(t.location)+' "}function v(e,o){n=e||1,a=void 0!==o?o:a;var r=new URLSearchParams({page:n,per_page:50});a&&r.set("q",a),l(t+"/items?"+r.toString()).then((function(t){if(t){var e=document.getElementById("productTableBody"),o=t.data||[];if(!o.length)return e.innerHTML='Sin productos',void(document.getElementById("productPagination").innerHTML="");i||(i=new VirtualScroll({container:e,rowHeight:48,buffer:3,renderRow:p,emptyHtml:'Sin productos'})),i.setData(o);var n=t.pagination||{},a=document.getElementById("productPagination");n.total_pages>1?a.innerHTML='":a.innerHTML=''+(n.total||0)+" productos"}}))}function y(){var t=document.getElementById("countLines"),e=document.createElement("div");e.className="count-row",e.innerHTML='',t.appendChild(e)}function g(){l(t+"/alerts").then((function(t){if(t){var e=t.data||[],o=document.getElementById("alertsContent");if(o)if(e.length){var n="",a=e.filter((function(t){return"critical"===t.severity})),r=e.filter((function(t){return"warning"===t.severity})),i=e.filter((function(t){return"critical"!==t.severity&&"warning"!==t.severity}));a.length&&(n+='
Criticas
'+a.length+"
",n+='
',a.forEach((function(t){var e="zero"===t.type?"AGOTADO":"low"===t.type?"BAJO":t.type.toUpperCase();n+=h(t,e,"critical")})),n+="
"),r.length&&(n+='
Advertencias
'+r.length+"
",n+='
',r.forEach((function(t){n+=h(t,"EXCESO","warning")})),n+="
"),i.length&&(n+='
Informativas
'+i.length+"
",n+='
',i.forEach((function(t){n+=h(t,"INFO","info")})),n+="
"),o.innerHTML=n}else o.innerHTML='

Sin alertas activas

'}}))}function h(t,e,o){return'
['+e+"] "+m(t.part_number)+" — "+m(t.name)+'
Stock: '+t.stock+(t.min_stock?" (min: "+t.min_stock+")":"")+(t.max_stock?" (max: "+t.max_stock+")":"")+" · Sucursal "+t.branch_id+"
"}function f(o){l(t+"/items/"+o).then((function(t){if(t&&!t.error){var n=t.history||[],a="";a+='
',t.image_url?(a+=''+m(t.name)+'',a+='
',a+='',a+='',a+="
"):(a+='
',a+='',a+='
Sin imagen
',a+="
",a+=''),a+='',a+="
",a+='
',a+='
No. Parte'+m(t.part_number)+"
",a+='
Nombre'+m(t.name)+"
",a+='
Marca'+m(t.brand)+"
",a+='
Codigo de Barras'+m(t.barcode)+"
",a+='
Ubicacion'+m(t.location||"-")+"
",a+='
Stock'+(t.stock||0)+"
",a+="
",a+='
',a+='
Costo$'+u(t.cost)+"
",a+='
Precio 1$'+u(t.price_1)+"
",a+='
Precio 2$'+u(t.price_2)+"
",a+='
Precio 3$'+u(t.price_3)+"
",a+="
",a+='
Cross-References / Equivalencias
',a+='
',a+='

Cargando equivalencias...

',a+="
";var r,i=t.part_number,s=t.catalog_part_id;r=s?"/pos/api/catalog/part/"+s:"/pos/api/catalog/search?q="+encodeURIComponent(i),fetch(r,{headers:{Authorization:"Bearer "+e}}).then((function(t){return t.json()})).then((function(t){var o=document.getElementById("crossRefContent");if(o){var n=t.alternatives||[],a=t.bodegas||[];!s&&t.data&&t.data.length>0?fetch("/pos/api/catalog/part/"+t.data[0].id_part,{headers:{Authorization:"Bearer "+e}}).then((function(t){return t.json()})).then((function(t){d(o,t.alternatives||[],t.bodegas||[])})).catch((function(){o.innerHTML='

Sin conexion al catalogo.

'})):d(o,n,a)}})).catch((function(){var t=document.getElementById("crossRefContent");t&&(t.innerHTML='

Sin conexion al catalogo central.

')})),a+='
Vehiculos Compatibles
',a+='
',a+='

Cargando compatibilidades...

',a+="
",fetch("/pos/api/inventory/items/"+o+"/vehicles",{headers:{Authorization:"Bearer "+e}}).then((function(t){return t.json()})).then((function(t){var e=document.getElementById("compatContent");if(e){var n=t.vehicles||[],a="";n.length>0?(a+='',n.forEach((function(t){a+="",a+=''})),a+="
MarcaModeloAnoMotorOrigen
"+m(t.brand||"")+""+m(t.model||"")+""+m(t.year||"")+""+m(t.engine||"")+""+m(t.source||"")+"
"):a+='

Sin vehiculos vinculados.

',a+='
Busca en catalogo central y vincula automaticamente
',e.innerHTML=a}})).catch((function(){var t=document.getElementById("compatContent");t&&(t.innerHTML='

Error al cargar compatibilidades.

')})),a+='
Historial de Movimientos
',n.length?(a+='',n.forEach((function(t){var e=t.quantity>0?"var(--color-success)":"var(--color-error)";a+='"})),a+="
FechaTipoCantidadCostoEmpleadoNotas
'+m(t.date)+""+m(t.type)+''+(t.quantity>0?"+":"")+t.quantity+''+(t.cost?"$"+u(t.cost):"—")+""+m(t.employee)+''+m(t.notes)+"
"):a+='

Sin movimientos

',document.getElementById("historyContent").innerHTML=a,document.getElementById("historyModal").classList.add("is-open")}else alert(t?t.error:"Error de red");function d(t,e,o){var n="";o&&o.length>0&&(n+='
Disponible en Bodegas:
',n+='',o.forEach((function(t){n+=""})),n+="
BodegaStockPrecioUbicacion
"+m(t.business_name||t.bodega||"")+""+(t.stock||t.stock_quantity||0)+'$'+u(t.price||0)+""+m(t.location||t.warehouse_location||"")+"
"),e&&e.length>0&&(n+='
Partes Equivalentes (Aftermarket):
',n+='',e.forEach((function(t){n+='"})),n+="
No. ParteFabricanteNombre
'+m(t.part_number||t.cross_reference_number||"")+""+m(t.manufacturer||t.source_ref||"")+""+m(t.name||t.name_aftermarket_parts||"")+"
"),n||(n='

No se encontraron equivalencias para esta parte.

'),t.innerHTML=n}}))}}(); \ No newline at end of file +!function(){"use strict";var t="/pos/api/inventory",e=localStorage.getItem("pos_token");if(e){var o={Authorization:"Bearer "+e,"Content-Type":"application/json"},n=1,a="",r=null,i=null,s=window.switchTab;window.switchTab=function(t){"function"==typeof s&&s(t),"alertas"===t&&g(),"stock"===t&&v(n)};var c,d=document.getElementById("productSearch");d&&d.addEventListener("input",(function(){clearTimeout(c),c=setTimeout((function(){v(1,d.value.trim())}),350)})),window._loadItems=function(t){v(t)},window.loadItems=function(t,e){v(t,e)},window.viewHistory=function(e){l(t+"/items/"+e+"/history").then((function(t){if(t){var e=t.data||[],o="";e.length?(o='',e.forEach((function(t){var e=t.quantity>0?"var(--color-success)":"var(--color-error)";o+='"})),o+="
FechaTipoCantidadCostoEmpleadoNotas
'+p(t.date)+""+p(t.type)+''+(t.quantity>0?"+":"")+t.quantity+''+(t.cost?"$"+u(t.cost):"—")+""+p(t.employee)+''+p(t.notes)+"
"):o='

Sin movimientos

',document.getElementById("historyContent").innerHTML=o,document.getElementById("historyModal").classList.add("is-open")}}))},window.viewProductDetail=f,window.uploadItemImage=function(o){var n=document.createElement("input");n.type="file",n.accept="image/jpeg,image/png,image/webp",n.onchange=function(){if(n.files&&n.files[0]){var a=n.files[0];if(a.size>5242880)alert("Imagen demasiado grande (max 5 MB)");else{var r=new FormData;r.append("file",a);var i=document.getElementById("imgUploadStatus");i&&(i.textContent="Subiendo..."),fetch(t+"/items/"+o+"/image",{method:"POST",headers:{Authorization:"Bearer "+e},body:r}).then((function(t){return t.json()})).then((function(t){t.image_url?f(o):i&&(i.textContent=t.error||"Error")})).catch((function(){i&&(i.textContent="Error de red")}))}}},n.click()},window.deleteItemImage=function(o){confirm("Eliminar imagen de este producto?")&&fetch(t+"/items/"+o+"/image",{method:"DELETE",headers:{Authorization:"Bearer "+e}}).then((function(t){return t.json()})).then((function(t){t.message?f(o):alert(t.error||"Error")})).catch((function(){alert("Error de red")}))},window.closeHistoryModal=function(){document.getElementById("historyModal").classList.remove("is-open")},window.showCreateModal=function(){document.getElementById("createModal").classList.add("is-open");var e=document.getElementById("newPartNumber");e&&!e._classifyBound&&(e._classifyBound=!0,e.addEventListener("blur",(function(){var e=this.value.trim();if(!(e.length<3)){var o,n,a=document.getElementById("newName");if(!a||!a.value.trim())o=e,(n=document.getElementById("createResult")).innerHTML='Consultando IA...',l(t+"/classify/"+encodeURIComponent(o)).then((function(t){if(t){t.name&&(document.getElementById("newName").value=t.name),t.brand&&(document.getElementById("newBrand").value=t.brand);var e=[];t.name&&e.push(t.name),t.brand&&e.push(t.brand),t.vehicle&&e.push(t.vehicle),t.category&&e.push(t.category),e.length>0?n.innerHTML='Sugerido por IA: '+p(e.join(" | "))+"":n.innerHTML='IA no pudo identificar este numero de parte'}})).catch((function(){n.innerHTML=""}))}})))},window.closeCreateModal=function(){document.getElementById("createModal").classList.remove("is-open"),document.getElementById("createResult").innerHTML=""},window.createItem=function(){var e={part_number:document.getElementById("newPartNumber").value.trim(),name:document.getElementById("newName").value.trim(),brand:document.getElementById("newBrand").value.trim(),barcode:document.getElementById("newBarcode").value.trim()||void 0,cost:parseFloat(document.getElementById("newCost").value)||0,price_1:parseFloat(document.getElementById("newPrice1").value)||0,price_2:parseFloat(document.getElementById("newPrice2").value)||0,price_3:parseFloat(document.getElementById("newPrice3").value)||0,min_stock:parseInt(document.getElementById("newMinStock").value)||0,initial_stock:parseInt(document.getElementById("newInitialStock").value)||0,location:document.getElementById("newLocation").value.trim()};e.part_number&&e.name?l(t+"/items",{method:"POST",body:JSON.stringify(e)}).then((function(t){if(t&&t.id){var e="Creado ID "+t.id+" | Barcode: "+t.barcode;t.vehicle_compatibilities_added>0&&(e+=" | "+t.vehicle_compatibilities_added+" vehiculo(s) asignado(s) por IA"),document.getElementById("createResult").innerHTML=''+e+"",v(n)}else document.getElementById("createResult").innerHTML=''+(t?t.error||"Error":"Error de red")+""})):document.getElementById("createResult").innerHTML='Numero de parte y nombre son obligatorios'},window.showPurchaseModal=function(){document.getElementById("purchaseModal").classList.add("is-open")},window.closePurchaseModal=function(){document.getElementById("purchaseModal").classList.remove("is-open"),document.getElementById("purchaseResult").innerHTML=""},window.recordPurchase=function(){var e={inventory_id:parseInt(document.getElementById("purchaseItemId").value),quantity:parseInt(document.getElementById("purchaseQty").value),unit_cost:parseFloat(document.getElementById("purchaseCost").value),supplier_invoice:document.getElementById("purchaseInvoice").value.trim(),notes:document.getElementById("purchaseNotes").value.trim()};e.inventory_id&&e.quantity&&e.unit_cost?l(t+"/purchase",{method:"POST",body:JSON.stringify(e)}).then((function(t){document.getElementById("purchaseResult").innerHTML=t&&t.operation_id?'Compra registrada (op #'+t.operation_id+")":''+(t?t.error||"Error":"Error de red")+""})):document.getElementById("purchaseResult").innerHTML='Complete todos los campos obligatorios'},window.showAdjustmentModal=function(){document.getElementById("adjustmentModal").classList.add("is-open")},window.closeAdjustmentModal=function(){document.getElementById("adjustmentModal").classList.remove("is-open"),document.getElementById("adjustResult").innerHTML=""},window.recordAdjustment=function(){var e={inventory_id:parseInt(document.getElementById("adjustItemId").value),quantity:parseInt(document.getElementById("adjustQty").value),reason:document.getElementById("adjustReason").value.trim()};e.inventory_id&&void 0!==e.quantity&&e.reason?l(t+"/adjustment",{method:"POST",body:JSON.stringify(e)}).then((function(t){document.getElementById("adjustResult").innerHTML=t&&t.operation_id?'Ajuste registrado (op #'+t.operation_id+")":''+(t?t.error||"Error":"Error de red")+""})):document.getElementById("adjustResult").innerHTML='Complete todos los campos (razon obligatoria)'},window.showTransferModal=function(){document.getElementById("transferModal").classList.add("is-open")},window.closeTransferModal=function(){document.getElementById("transferModal").classList.remove("is-open"),document.getElementById("transferResult").innerHTML=""},window.recordTransfer=function(){var e={inventory_id:parseInt(document.getElementById("transferItemId").value),from_branch_id:parseInt(document.getElementById("transferFrom").value),to_branch_id:parseInt(document.getElementById("transferTo").value),quantity:parseInt(document.getElementById("transferQty").value),notes:document.getElementById("transferNotes").value.trim()};e.inventory_id&&e.from_branch_id&&e.to_branch_id&&e.quantity?l(t+"/transfer",{method:"POST",body:JSON.stringify(e)}).then((function(t){document.getElementById("transferResult").innerHTML=t&&t.out_operation_id?'Transferencia registrada':''+(t?t.error||"Error":"Error de red")+""})):document.getElementById("transferResult").innerHTML='Complete todos los campos'},window.showCountModal=function(){document.getElementById("countModal").classList.add("is-open"),document.querySelectorAll("#countLines .count-row").length||y()},window.closeCountModal=function(){document.getElementById("countModal").classList.remove("is-open")},window.addCountLine=y,window.startPhysicalCount=function(){var e=document.querySelectorAll("#countLines .count-row"),o=[];e.forEach((function(t){var e=parseInt(t.querySelector(".count-inv-id").value),n=parseInt(t.querySelector(".count-qty").value);e&&!isNaN(n)&&o.push({inventory_id:e,counted_quantity:n})})),o.length?l(t+"/physical-count/start",{method:"POST",body:JSON.stringify({items:o})}).then((function(t){if(t&&t.count_id){r=t.count_id;var e='

Borrador #'+t.count_id+" — "+p(t.message)+"

";e+='',(t.results||[]).forEach((function(t){var o=0===t.difference?"var(--color-success)":t.difference<0?"var(--color-error)":"var(--color-warning)";e+=""})),e+="
IDEsperadoContadoDiferencia
"+t.inventory_id+""+t.expected+""+t.counted+''+(t.difference>0?"+":"")+t.difference+"
",e+='
',e+='',e+='',e+="
",document.getElementById("countResults").innerHTML=e}else document.getElementById("countResults").innerHTML=''+(t?t.error||"Error":"Error de red")+""})):alert("Agregue al menos una linea")},window.approvePhysicalCount=function(){r?l(t+"/physical-count/approve",{method:"POST",body:JSON.stringify({count_id:r})}).then((function(t){t&&"approved"===t.status?(document.getElementById("countResults").innerHTML=''+p(t.message)+"",r=null):document.getElementById("countResults").innerHTML+='
'+(t?t.error||"Error":"Error de red")+""})):alert("No hay borrador activo")},window.cancelDraft=function(){r=null,document.getElementById("countResults").innerHTML='Borrador cancelado'},window.loadAlerts=g,window.printBarcode=function(t,e,o){var n=window.open("","_blank","width=400,height=250");n.document.write("Etiqueta"),n.document.write("

"+t+"

"),n.document.write("

"+e+"

"),n.document.write('

'+o+"

"),n.document.write(""),n.document.close(),n.print()},window.autoMatchCompat=function(t){fetch("/pos/api/inventory/items/"+t+"/vehicles/auto-match",{method:"POST",headers:{Authorization:"Bearer "+e}}).then((function(t){return t.json()})).then((function(e){alert("Auto-match completado. Vehiculos vinculados: "+(e.matched||0)),f(t)})).catch((function(){alert("Error en auto-match")}))},window.removeCompat=function(t,o){confirm("Quitar compatibilidad con este vehiculo?")&&fetch("/pos/api/inventory/items/"+t+"/compatibility/"+o,{method:"DELETE",headers:{Authorization:"Bearer "+e}}).then((function(t){return t.json()})).then((function(){f(t)})).catch((function(){alert("Error al quitar compatibilidad")}))},v(1)}else window.location.href="/pos/login";function l(t,e){return fetch(t,Object.assign({headers:o},e||{})).then((function(t){return 401===t.status?(localStorage.removeItem("pos_token"),window.location.href="/pos/login",null):t.json()}))}function u(t){return(parseFloat(t)||0).toFixed(2)}function p(t){if(!t)return"";var e=document.createElement("div");return e.textContent=t,e.innerHTML}function m(t){return''+p(t.barcode)+''+p(t.part_number)+''+p(t.name)+""+p(t.brand)+''+t.stock+'$'+u(t.cost)+'$'+u(t.price_1)+'$'+u(t.price_2)+'$'+u(t.price_3)+""+p(t.location)+' "}function v(e,o){n=e||1,a=void 0!==o?o:a;var r=new URLSearchParams({page:n,per_page:50});a&&r.set("q",a),l(t+"/items?"+r.toString()).then((function(t){if(t){var e=document.getElementById("productTableBody"),o=t.data||[];if(!o.length)return e.innerHTML='Sin productos',void(document.getElementById("productPagination").innerHTML="");i||(i=new VirtualScroll({container:e,rowHeight:48,buffer:3,renderRow:m,emptyHtml:'Sin productos'})),i.setData(o);var n=t.pagination||{},a=document.getElementById("productPagination");n.total_pages>1?a.innerHTML='":a.innerHTML=''+(n.total||0)+" productos"}}))}function y(){var t=document.getElementById("countLines"),e=document.createElement("div");e.className="count-row",e.innerHTML='',t.appendChild(e)}function g(){l(t+"/alerts").then((function(t){if(t){var e=t.data||[],o=document.getElementById("alertsContent");if(o)if(e.length){var n="",a=e.filter((function(t){return"critical"===t.severity})),r=e.filter((function(t){return"warning"===t.severity})),i=e.filter((function(t){return"critical"!==t.severity&&"warning"!==t.severity}));a.length&&(n+='
Criticas
'+a.length+"
",n+='
',a.forEach((function(t){var e="zero"===t.type?"AGOTADO":"low"===t.type?"BAJO":t.type.toUpperCase();n+=h(t,e,"critical")})),n+="
"),r.length&&(n+='
Advertencias
'+r.length+"
",n+='
',r.forEach((function(t){n+=h(t,"EXCESO","warning")})),n+="
"),i.length&&(n+='
Informativas
'+i.length+"
",n+='
',i.forEach((function(t){n+=h(t,"INFO","info")})),n+="
"),o.innerHTML=n}else o.innerHTML='

Sin alertas activas

'}}))}function h(t,e,o){return'
['+e+"] "+p(t.part_number)+" — "+p(t.name)+'
Stock: '+t.stock+(t.min_stock?" (min: "+t.min_stock+")":"")+(t.max_stock?" (max: "+t.max_stock+")":"")+" · Sucursal "+t.branch_id+"
"}function f(o){l(t+"/items/"+o).then((function(t){if(t&&!t.error){var n=t.history||[],a="";a+='
',t.image_url?(a+=''+p(t.name)+'',a+='
',a+='',a+='',a+="
"):(a+='
',a+='',a+='
Sin imagen
',a+="
",a+=''),a+='',a+="
",a+='
',a+='
No. Parte'+p(t.part_number)+"
",a+='
Nombre'+p(t.name)+"
",a+='
Marca'+p(t.brand)+"
",a+='
Codigo de Barras'+p(t.barcode)+"
",a+='
Ubicacion'+p(t.location||"-")+"
",a+='
Stock'+(t.stock||0)+"
",a+="
",a+='
',a+='
Costo$'+u(t.cost)+"
",a+='
Precio 1$'+u(t.price_1)+"
",a+='
Precio 2$'+u(t.price_2)+"
",a+='
Precio 3$'+u(t.price_3)+"
",a+="
",a+='
Cross-References / Equivalencias
',a+='
',a+='

Cargando equivalencias...

',a+="
";var r,i=t.part_number,s=t.catalog_part_id;r=s?"/pos/api/catalog/part/"+s:"/pos/api/catalog/search?q="+encodeURIComponent(i),fetch(r,{headers:{Authorization:"Bearer "+e}}).then((function(t){return t.json()})).then((function(t){var o=document.getElementById("crossRefContent");if(o){var n=t.alternatives||[],a=t.bodegas||[];!s&&t.data&&t.data.length>0?fetch("/pos/api/catalog/part/"+t.data[0].id_part,{headers:{Authorization:"Bearer "+e}}).then((function(t){return t.json()})).then((function(t){c(o,t.alternatives||[],t.bodegas||[])})).catch((function(){o.innerHTML='

Sin conexion al catalogo.

'})):c(o,n,a)}})).catch((function(){var t=document.getElementById("crossRefContent");t&&(t.innerHTML='

Sin conexion al catalogo central.

')})),a+='
Vehiculos Compatibles
',a+='
',a+='

Cargando compatibilidades...

',a+="
",fetch("/pos/api/inventory/items/"+o+"/vehicles",{headers:{Authorization:"Bearer "+e}}).then((function(t){return t.json()})).then((function(t){var e=document.getElementById("compatContent");if(e){var n=t.vehicles||[],a="";n.length>0?(a+='',n.forEach((function(t){var e="qwen_ai"===t.source?'IA':"auto_match"===t.source?'TecDoc':p(t.source||"");a+="",a+=''})),a+="
MarcaModeloAnoMotorOrigen
"+p(t.brand||"")+""+p(t.model||"")+""+p(t.year||"")+""+p(t.engine||"")+""+e+"
"):a+='

Sin vehiculos vinculados.

',a+='
Busca en catalogo central y vincula automaticamente
',e.innerHTML=a}})).catch((function(){var t=document.getElementById("compatContent");t&&(t.innerHTML='

Error al cargar compatibilidades.

')})),a+='
Historial de Movimientos
',n.length?(a+='',n.forEach((function(t){var e=t.quantity>0?"var(--color-success)":"var(--color-error)";a+='"})),a+="
FechaTipoCantidadCostoEmpleadoNotas
'+p(t.date)+""+p(t.type)+''+(t.quantity>0?"+":"")+t.quantity+''+(t.cost?"$"+u(t.cost):"—")+""+p(t.employee)+''+p(t.notes)+"
"):a+='

Sin movimientos

',document.getElementById("historyContent").innerHTML=a,document.getElementById("historyModal").classList.add("is-open")}else alert(t?t.error:"Error de red");function c(t,e,o){var n="";o&&o.length>0&&(n+='
Disponible en Bodegas:
',n+='',o.forEach((function(t){n+=""})),n+="
BodegaStockPrecioUbicacion
"+p(t.business_name||t.bodega||"")+""+(t.stock||t.stock_quantity||0)+'$'+u(t.price||0)+""+p(t.location||t.warehouse_location||"")+"
"),e&&e.length>0&&(n+='
Partes Equivalentes (Aftermarket):
',n+='',e.forEach((function(t){n+='"})),n+="
No. ParteFabricanteNombre
'+p(t.part_number||t.cross_reference_number||"")+""+p(t.manufacturer||t.source_ref||"")+""+p(t.name||t.name_aftermarket_parts||"")+"
"),n||(n='

No se encontraron equivalencias para esta parte.

'),t.innerHTML=n}}))}}(); \ No newline at end of file