import { allRows, parseRequest, regionByMarketplace, shopPointer, } from './sp-api-collector-lib.mjs'; async function batch(requests) { for (let start = 0; start < requests.length; start += 25) { const result = await parseRequest('/batch', 'POST', { requests: requests.slice(start, start + 25) }); const error = result.find?.(item => item.error)?.error; if (error) throw new Error(error.error || error.code || 'Parse batch failed'); } } async function dedupeRecordKeys(className) { const rows = await allRows(className, 'objectId,recordKey'); const seen = new Set(); const deletes = []; for (const row of rows) { if (!row.recordKey || seen.has(row.recordKey)) { deletes.push({ method: 'DELETE', path: `/parse/classes/${className}/${row.objectId}` }); } else { seen.add(row.recordKey); } } await batch(deletes); return { before: rows.length, deleted: deletes.length, after: rows.length - deletes.length }; } const shops = await allRows('Shop', 'objectId,marketplaceId'); const shopById = new Map(shops.map(shop => [shop.objectId, shop])); const shipments = await allRows('AmazonInboundShipment'); const groups = new Map(); for (const row of shipments) { const shop = shopById.get(row.shop?.objectId); const region = row.region || regionByMarketplace[shop?.marketplaceId] || 'UNKNOWN'; const businessKey = `${region}:${row.shipmentId || row.recordKey || row.objectId}`; if (!groups.has(businessKey)) groups.set(businessKey, []); groups.get(businessKey).push({ ...row, region }); } const shipmentUpdates = []; const shipmentDeletes = []; for (const [recordKey, rows] of groups) { const keep = rows[0]; shipmentUpdates.push({ method: 'PUT', path: `/parse/classes/AmazonInboundShipment/${keep.objectId}`, body: { recordKey, region: keep.region }, }); for (const row of rows.slice(1)) { shipmentDeletes.push({ method: 'DELETE', path: `/parse/classes/AmazonInboundShipment/${row.objectId}` }); } } await batch(shipmentUpdates); await batch(shipmentDeletes); const results = { AmazonInboundShipment: { before: shipments.length, uniqueShipments: groups.size, deleted: shipmentDeletes.length, after: groups.size, }, }; for (const className of [ 'SpApiSellerAccount', 'SpApiMarketplaceParticipation', 'AmazonInventorySummary', 'AmazonSalesMetric', 'AmazonCatalogItem', 'AmazonProductPricing', 'AmazonOrderItem', 'AmazonFinancialEvent', 'AmazonCustomerFeedback', 'AmazonReportRow', ]) { results[className] = await dedupeRecordKeys(className); } console.log(JSON.stringify(results, null, 2));