fix: Correct stock column detection for PANEU-Stock.xlsx

- Prioritize 'Sellable On Hand Units' column (was selecting 'Net Received Units')
- Add 'Store code' recognition for marketplace detection
- Improved column search strategy with priority levels
This commit is contained in:
Christian Vidal Wolf
2026-02-02 09:18:32 +01:00
parent 7e58e8aba4
commit ab9ac4f47e
+35 -21
View File
@@ -1897,38 +1897,51 @@ export const processVendorStockExcel = async (fileOrBuffer: File | ArrayBuffer):
const headers: any[] = jsonData[headerRowIndex];
const asinIdx = headers.findIndex(h => String(h || '').toUpperCase() === 'ASIN');
// Enhanced marketplace detection - includes 'Store code' for PANEU reports
const marketplaceIdx = headers.findIndex(h => {
const sh = String(h || '').toUpperCase();
return sh === 'MARKETPLACE' || sh === 'COUNTRY' || sh === 'COUNTRY/REGION';
return sh === 'MARKETPLACE' || sh === 'COUNTRY' || sh === 'COUNTRY/REGION' ||
sh === 'STORE CODE' || sh === 'STORE';
});
const stockIdx = headers.findIndex(h => {
const sh = String(h || '').toUpperCase();
// EXCLUSION LIST: Skip columns that are clearly monetary or unrelated
if (sh.includes('COST') || sh.includes('VALUE') || sh.includes('AMOUNT') || sh.includes('PRICE') || sh.includes('CURRENCY') || sh.includes('SC')) {
return false;
}
// PRIORITY LIST: Look for Units/Qty specific keywords
return sh.includes('UNITS') || sh.includes('QTY') || sh.includes('QUANTITY') ||
// Fallback to generic stock terms if specific unit terms aren't found,
// but only if we haven't found a better match yet (implemented via logic flow below)
sh.includes('ON HAND') || sh.includes('SELLABLE') || sh.includes('STOCK') || sh.includes('AVAILABILITY');
});
// REFINED SEARCH STRATEGY:
// 1. First pass: strict "Units/Qty" search
// REFINED SEARCH STRATEGY for Stock column:
// Priority 1: Look specifically for "Sellable On Hand Units" (most accurate for current inventory)
let finalStockIdx = headers.findIndex(h => {
const sh = String(h || '').toUpperCase();
return (sh.includes('UNITS') || sh.includes('QTY') || sh.includes('QUANTITY')) &&
!sh.includes('COST') && !sh.includes('VALUE') && !sh.includes('AMOUNT');
return sh === 'SELLABLE ON HAND UNITS';
});
// 2. Second pass: "On Hand" / "Stock" (if no Units found)
// Priority 2: Look for columns with "SELLABLE" AND "UNITS" (but not necessarily exact match)
if (finalStockIdx === -1) {
finalStockIdx = headers.findIndex(h => {
const sh = String(h || '').toUpperCase();
return (sh.includes('ON HAND') || sh.includes('SELLABLE') || sh.includes('STOCK') || sh.includes('AVAILABILITY')) &&
!sh.includes('COST') && !sh.includes('VALUE') && !sh.includes('AMOUNT');
return sh.includes('SELLABLE') && sh.includes('UNITS') &&
!sh.includes('UNSELLABLE') && !sh.includes('AGED');
});
}
// Priority 3: Look for "On Hand Units" variations
if (finalStockIdx === -1) {
finalStockIdx = headers.findIndex(h => {
const sh = String(h || '').toUpperCase();
return sh.includes('ON HAND') && sh.includes('UNITS') &&
!sh.includes('UNSELLABLE');
});
}
// Priority 4: Fallback to generic stock column search (but avoid monetary columns)
if (finalStockIdx === -1) {
finalStockIdx = headers.findIndex(h => {
const sh = String(h || '').toUpperCase();
// Exclude columns that are clearly wrong
if (sh.includes('COST') || sh.includes('VALUE') || sh.includes('AMOUNT') ||
sh.includes('PRICE') || sh.includes('RECEIVED') || sh.includes('UNFILLED') ||
sh.includes('AGED') || sh.includes('UNSELLABLE')) {
return false;
}
return sh.includes('STOCK') || sh.includes('AVAILABILITY') ||
(sh.includes('UNITS') && sh.includes('SELLABLE'));
});
}
@@ -1938,6 +1951,7 @@ export const processVendorStockExcel = async (fileOrBuffer: File | ArrayBuffer):
finalStockIdx = finalStockIdx !== -1 ? finalStockIdx : 15;
console.log(`[VendorStock] Selected Stock Column: "${headers[finalStockIdx]}" (Index: ${finalStockIdx})`);
console.log(`[VendorStock] Marketplace Column: "${headers[finalMarketplaceIdx]}" (Index: ${finalMarketplaceIdx})`);
for (let i = headerRowIndex + 1; i < jsonData.length; i++) {
const row = jsonData[i];