diff --git a/services/dataProcessor.ts b/services/dataProcessor.ts index 8926582..544bfd4 100644 --- a/services/dataProcessor.ts +++ b/services/dataProcessor.ts @@ -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];