feat: enhance stalker functionality with inventory sellability checks and update frontend display

This commit is contained in:
Victor Noguera
2026-05-19 18:35:55 -04:00
parent a7c0e44e3d
commit aed0c11017
6 changed files with 317 additions and 78 deletions

View File

@@ -58,22 +58,15 @@ type StalkerResultRecord = {
started_at: string;
status: string;
input_file: string;
source_asin: string;
title: string | null;
offer_count: number;
candidate_seller_count: number;
matched_seller_count: number;
scan_fetched_at: string;
seller_id: string;
seller_name: string | null;
rating: number | null;
rating_count: number | null;
storefront_asin_total: number | null;
persisted_inventory_sample_count: number | null;
offer_price: number | null;
condition: string | null;
is_fba: number | null;
stock: number | null;
discovered_from_count: number;
first_seen_at: string;
last_seen_at: string;
persisted_inventory_asin_count: number;
inventory_sample_asins: string | null;
};
@@ -690,14 +683,14 @@ function parseStalkerFilters(filters: URLSearchParams) {
if (q) {
const wildcard = `%${q}%`;
conditions.push(
`(sc.source_asin LIKE ? OR sc.title LIKE ? OR s.seller_id LIKE ? OR s.seller_name LIKE ? OR EXISTS (
`(s.seller_id LIKE ? OR s.seller_name LIKE ? OR EXISTS (
SELECT 1 FROM stalker_seller_inventory inv_q
WHERE inv_q.run_id = r.id
AND inv_q.seller_id = s.seller_id
AND inv_q.asin LIKE ?
))`,
);
params.push(wildcard, wildcard, wildcard, wildcard, wildcard);
params.push(wildcard, wildcard, wildcard);
}
return {
@@ -710,22 +703,19 @@ function parseStalkerSort(sortParam: string | null): string {
const allowedSort = new Set([
"runId",
"started_at",
"source_asin",
"title",
"seller_id",
"seller_name",
"rating",
"rating_count",
"offer_price",
"stock",
"discovered_from_count",
"persisted_inventory_asin_count",
"storefront_asin_total",
"scan_fetched_at",
"last_seen_at",
]);
const parsed = parseSort(
sortParam,
allowedSort,
"started_at DESC, runId DESC, source_asin ASC",
"persisted_inventory_asin_count DESC, last_seen_at DESC, seller_id ASC",
);
return parsed
@@ -751,22 +741,15 @@ function getStalkerResults(filters: URLSearchParams) {
r.started_at,
r.status,
r.input_file,
sc.source_asin,
sc.title,
sc.offer_count,
sc.candidate_seller_count,
sc.matched_seller_count,
sc.fetched_at AS scan_fetched_at,
s.seller_id,
s.seller_name,
s.rating,
s.rating_count,
s.storefront_asin_total,
s.persisted_inventory_sample_count,
sas.offer_price,
sas.condition,
sas.is_fba,
sas.stock,
COUNT(DISTINCT sc.source_asin) AS discovered_from_count,
MIN(sc.fetched_at) AS first_seen_at,
MAX(sc.fetched_at) AS last_seen_at,
COUNT(DISTINCT inv.asin) AS persisted_inventory_asin_count,
GROUP_CONCAT(DISTINCT inv.asin) AS inventory_sample_asins
FROM stalker_asin_sellers sas
@@ -777,7 +760,7 @@ function getStalkerResults(filters: URLSearchParams) {
ON inv.run_id = r.id
AND inv.seller_id = s.seller_id
${where}
GROUP BY sas.id
GROUP BY r.id, s.seller_id
`;
const totalRow = db
@@ -788,14 +771,12 @@ function getStalkerResults(filters: URLSearchParams) {
.query(
`SELECT
COUNT(DISTINCT runId) AS runs,
COUNT(DISTINCT source_asin) AS sourceAsins,
COUNT(DISTINCT seller_id) AS sellers,
COALESCE(SUM(persisted_inventory_asin_count), 0) AS persistedInventoryAsins
FROM (${baseSelect}) stalker_rows`,
)
.get(...params) as {
runs: number;
sourceAsins: number;
sellers: number;
persistedInventoryAsins: number;
};