Refactor mid-range seller processing to enforce sellability gates and enhance command-line arguments

- Updated test case to reflect changes in processing mid-range matches based on sellability.
- Modified `processCategory` function to implement strict and soft sellability gates.
- Introduced new command-line arguments for category selection and sellability gate configuration.
- Enhanced error handling and validation for new arguments.
- Improved logging for category processing and budget usage.
This commit is contained in:
Victor Noguera
2026-05-12 14:14:20 -04:00
parent f2c8a9728d
commit 41ef57a7bc
5 changed files with 681 additions and 404 deletions

View File

@@ -2,27 +2,57 @@ import { readProducts } from "./reader.ts";
import { connectCache, disconnectCache } from "./cache.ts";
import { printResults, writeResultsToDb } from "./writer.ts";
import { initDb, closeDb } from "./database.ts";
import { chunkArray, processProductChunk } from "./analysis-pipeline.ts";
import {
chunkArray,
processProductChunk,
type SellabilityFilter,
} from "./analysis-pipeline.ts";
import path from "node:path";
import type { AnalysisResult } from "./types.ts";
const DB_PATH = "./results.db";
const INPUT_BATCH_SIZE = 50;
function parseArgs(): { inputFile: string; outputFile?: string } {
function parseSellabilityArg(args: string[]): SellabilityFilter {
const sellabilityArg = args.find((a) => a.startsWith("--sellability="));
const sellabilityValueFromEquals = sellabilityArg?.split("=")[1];
const sellabilityIdx = args.indexOf("--sellability");
const sellabilityValueFromNext =
sellabilityIdx !== -1 ? args[sellabilityIdx + 1] : undefined;
const rawSellability = sellabilityValueFromEquals ?? sellabilityValueFromNext;
if (!rawSellability) return "available";
const normalized = rawSellability.toLowerCase();
if (normalized === "available" || normalized === "all") {
return normalized;
}
console.error(
`Invalid --sellability value: \"${rawSellability}\". Use \"available\" or \"all\".`,
);
process.exit(1);
}
function parseArgs(): {
inputFile: string;
outputFile?: string;
sellability: SellabilityFilter;
} {
const args = process.argv.slice(2);
const inputFile = args.find((a) => !a.startsWith("--"));
const outIdx = args.indexOf("--out");
const outputFile = outIdx !== -1 ? args[outIdx + 1] : undefined;
const sellability = parseSellabilityArg(args);
if (!inputFile) {
console.error(
"Usage: bun run src/index.ts <input.csv|xlsx> [--out results.csv]",
"Usage: bun run src/index.ts <input.csv|xlsx> [--out results.csv] [--sellability available|all]",
);
process.exit(1);
}
return { inputFile, outputFile };
return { inputFile, outputFile, sellability };
}
function resolveBaseOutputPath(inputFile: string, outputFile?: string): string {
@@ -33,7 +63,9 @@ function resolveBaseOutputPath(inputFile: string, outputFile?: string): string {
}
async function main() {
const { inputFile, outputFile } = parseArgs();
const { inputFile, outputFile, sellability } = parseArgs();
console.log(`Sellability filter: ${sellability}`);
console.log("Connecting to Redis...");
await connectCache();
@@ -66,7 +98,7 @@ async function main() {
console.log(
`\n=== Input chunk ${chunkIndex + 1}/${productChunks.length} (${chunk.length} products) ===`,
);
const chunkResults = await processProductChunk(chunk);
const chunkResults = await processProductChunk(chunk, { sellability });
allResults.push(...chunkResults);
}