Opción C: Vinculación híbrida de inventario local con vehículos
- Nueva tabla inventory_vehicle_compat (v3.1) - Motor inventory_vehicle_compat.py: auto-match + gestión manual - catalog_service.get_parts_local() ahora incluye piezas locales vinculadas - inventory_bp: auto-match en create/update + endpoints REST /vehicles - Frontend catalog.js: badge 'Stock Local' para piezas nativas del tenant - Frontend inventory.js: panel de vehículos compatibles con auto-match - Tests: test_compatibility.py (9/9 pasan) Piezas locales aparecen en navegación por vehículo aunque no estén en TecDoc. Auto-match busca part_number en parts/aftermarket_parts y copia MYEs compatibles.
This commit is contained in:
@@ -875,7 +875,11 @@
|
||||
|
||||
partsGrid.querySelectorAll('.part-card').forEach(function (card) {
|
||||
card.addEventListener('click', function () {
|
||||
openPartDetail(parseInt(this.dataset.partId));
|
||||
var pid = this.dataset.partId;
|
||||
if (typeof pid === 'string' && pid.indexOf('inv:') === 0) {
|
||||
return;
|
||||
}
|
||||
openPartDetail(parseInt(pid));
|
||||
});
|
||||
});
|
||||
|
||||
@@ -940,6 +944,10 @@
|
||||
} else {
|
||||
stockBadge = '<span class="stock-badge stock-badge--none">Sin stock</span>';
|
||||
}
|
||||
// Local inventory native badge
|
||||
var sourceBadge = p.source === 'local_inventory'
|
||||
? '<span class="stock-badge stock-badge--local" style="margin-left:4px;background:#4f46e5;">Stock Local</span>'
|
||||
: '';
|
||||
|
||||
var imgHtml = p.image_url
|
||||
? '<img src="' + esc(p.image_url) + '" alt="' + esc(p.name) + '">'
|
||||
@@ -961,10 +969,11 @@
|
||||
? esc(p.part_number) + '<span class="part-card__oem-sub"> · OEM: ' + esc(p.oem_part_number) + '</span>'
|
||||
: esc(p.oem_part_number);
|
||||
|
||||
return '<article class="part-card' + tierClass + '" role="listitem" data-part-id="' + p.id_part + '">' +
|
||||
return '<article class="part-card' + tierClass + '" role="listitem" data-part-id="' + p.id_part + '" data-source="' + (p.source || '') + '">' +
|
||||
'<div class="part-card__image">' + imgHtml + '</div>' +
|
||||
'<div class="part-card__body">' +
|
||||
manuBadge +
|
||||
sourceBadge +
|
||||
'<div class="part-card__oem">' + skuLine + '</div>' +
|
||||
'<div class="part-card__name">' + esc(p.name) + '</div>' +
|
||||
'</div>' +
|
||||
@@ -975,10 +984,15 @@
|
||||
'</article>';
|
||||
}).join('');
|
||||
|
||||
// Wire part card clicks → open detail panel
|
||||
// Wire part card clicks → open detail panel (skip local-inventory items)
|
||||
partsGrid.querySelectorAll('.part-card').forEach(function (card) {
|
||||
card.addEventListener('click', function () {
|
||||
openPartDetail(parseInt(this.dataset.partId));
|
||||
var pid = this.dataset.partId;
|
||||
if (typeof pid === 'string' && pid.indexOf('inv:') === 0) {
|
||||
// local-inventory item: info already visible on card
|
||||
return;
|
||||
}
|
||||
openPartDetail(parseInt(pid));
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1345,7 +1359,11 @@
|
||||
searchDropdown.querySelectorAll('.search-result-item').forEach(function (el) {
|
||||
el.addEventListener('click', function () {
|
||||
searchDropdown.classList.remove('is-visible');
|
||||
openPartDetail(parseInt(this.dataset.partId));
|
||||
var pid = this.dataset.partId;
|
||||
if (typeof pid === 'string' && pid.indexOf('inv:') === 0) {
|
||||
return;
|
||||
}
|
||||
openPartDetail(parseInt(pid));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user