feat: update Keepa and Stalker functionalities with enhanced price extraction logic and test cases

This commit is contained in:
Victor Noguera
2026-05-19 19:59:20 -04:00
parent 0552d183b3
commit 7bda3710ed
4 changed files with 30 additions and 24 deletions

View File

@@ -48,7 +48,7 @@ test("lookupKeepaUpcs returns found, not_found, and multiple_asins outcomes", as
current: [null, null, null, 1234],
avg: [2500, null, null, 1400],
},
csv: [[1, 2999]],
csv: [[5000000, 2999, 5000100]],
},
{
asin: "B000MULTI01",
@@ -85,6 +85,7 @@ test("lookupKeepaUpcs returns found, not_found, and multiple_asins outcomes", as
expect(details.get("012345678901")?.status).toBe("found");
expect(details.get("012345678901")?.asin).toBe("B000FOUND01");
expect(details.get("012345678901")?.keepaData?.currentPrice).toBe(29.99);
expect(details.get("012345678901")?.keepaData?.currentPrice).toBe(29.99);
expect(details.get("098765432109")?.status).toBe("multiple_asins");
expect(details.get("098765432109")?.candidateAsins).toEqual([

View File

@@ -529,14 +529,17 @@ function computeAmazonBuyBoxSharePctFromHistory(
return Math.round((amazonMinutes / qualifiedMinutes) * 10_000) / 100;
}
function extractLatestPositivePrice(series: unknown): number | null {
if (!Array.isArray(series) || series.length < 2) return null;
const last = series[series.length - 1];
if (typeof last !== "number" || !Number.isFinite(last) || last <= 0) {
return null;
}
return last / 100;
}
function extractLatestPositivePrice(series: unknown): number | null {
if (!Array.isArray(series) || series.length < 2) return null;
for (let i = series.length - 1; i >= 1; i--) {
if (i % 2 === 0) continue;
const value = series[i];
if (typeof value === "number" && Number.isFinite(value) && value > 0) {
return value / 100;
}
}
return null;
}
function pickKeepaNumber(...values: unknown[]): number | null {
for (const value of values) {
@@ -548,16 +551,14 @@ function pickKeepaNumber(...values: unknown[]): number | null {
return null;
}
function extractCurrentPrice(csv: number[][] | undefined): number | null {
if (!csv) return null;
// csv[0] = Amazon price history, csv[1] = Marketplace new price history
// Each is [time, price, time, price, ...] — last value is most recent
for (const series of [csv[0], csv[1]]) {
if (series && series.length >= 2) {
const lastPrice = series[series.length - 1]!;
if (lastPrice > 0) return lastPrice / 100;
}
}
return null;
}
function extractCurrentPrice(csv: number[][] | undefined): number | null {
if (!csv) return null;
// csv[0] = Amazon price history, csv[1] = Marketplace new price history
// Each is [time, price, time, price, ...]. Only odd indexes are prices.
for (const series of [csv[0], csv[1]]) {
const latestPrice = extractLatestPositivePrice(series);
if (latestPrice != null) return latestPrice;
}
return null;
}

View File

@@ -89,7 +89,7 @@ test("sellability checks matched seller inventory, not the source ASIN", async (
current: [null, null, null, 12345, null, null, null, null, null, null, null, 7],
avg: [2500],
},
csv: [[0, 1999]],
csv: [[5000000, 1999, 5000100]],
},
],
tokensLeft: 10,

View File

@@ -1355,7 +1355,11 @@ function extractCurrentPrice(csv: unknown): number | null {
function extractLatestPositiveKeepaPrice(history: unknown): number | null {
if (!Array.isArray(history)) return null;
for (let i = history.length - 1; i >= 0; i--) {
// Keepa CSV histories are [time, value, time, value, ...]. Only odd indexes
// are prices; even indexes are Keepa timestamps and can look like huge prices.
for (let i = history.length - 1; i >= 1; i--) {
if (i % 2 === 0) continue;
const value = extractNumber(history[i]);
if (value != null && value > 0) return value / 100;
}