feat: Implement supplier export functionality with workbook generation
- Add `writeSupplierWorkbook` function to create Excel workbooks for supplier analysis results. - Introduce `SupplierExportSummary` type for summarizing export data. - Create tests for `writeSupplierWorkbook` to ensure correct sheet creation and data population. - Implement supplier scoring logic in `supplier-scoring.ts` to evaluate product profitability and demand. - Add tests for supplier scoring to validate scoring logic and verdict determination. - Enhance UPC file analysis to integrate supplier scoring and export results to Excel. - Update database writing logic to accommodate new supplier analysis results. - Refactor types to include supplier-specific data structures and scoring metrics. - Ensure proper cleanup of temporary files after tests.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { getDb } from "./database.ts";
|
||||
import type { AnalysisResult } from "./types.ts";
|
||||
import type { AnalysisResult, SupplierAnalysisResult } from "./types.ts";
|
||||
|
||||
export type RunCounts = {
|
||||
totalProducts: number;
|
||||
@@ -222,6 +222,83 @@ export function appendResultsToRun(
|
||||
})();
|
||||
}
|
||||
|
||||
export function appendSupplierResultsToRun(
|
||||
dbPath: string,
|
||||
runId: number,
|
||||
results: SupplierAnalysisResult[],
|
||||
): void {
|
||||
if (results.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const database = getDb(dbPath);
|
||||
const insertResult = database.prepare(
|
||||
`INSERT INTO results (
|
||||
run_id, asin, product_name, brand, category, unit_cost, current_price,
|
||||
avg_price_90d, sales_rank, rank_avg_90d, sellers,
|
||||
amazon_is_seller, amazon_buybox_share_pct_90d, monthly_sold,
|
||||
rank_drops_30d, rank_drops_90d, upc, fba_fee, fbm_fee,
|
||||
referral_percent, supplier_score, supplier_profit, supplier_margin,
|
||||
supplier_roi, supplier_reason, upc_lookup_status, upc_lookup_reason,
|
||||
candidate_asins, can_sell, sellability_status, sellability_reason,
|
||||
verdict, confidence, reasoning, fetched_at
|
||||
) VALUES (
|
||||
?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,
|
||||
?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
|
||||
)`,
|
||||
);
|
||||
|
||||
database.transaction(() => {
|
||||
for (const result of results) {
|
||||
const keepa = result.keepa;
|
||||
const spApi = result.spApi;
|
||||
const asin = result.lookup.asin ?? result.record.asin ?? result.upc;
|
||||
const category =
|
||||
result.record.category ?? keepa?.categoryTree?.join(" > ") ?? null;
|
||||
const canSell =
|
||||
spApi?.canSell == null ? null : spApi.canSell ? "yes" : "no";
|
||||
|
||||
insertResult.run(
|
||||
runId,
|
||||
asin,
|
||||
result.record.name,
|
||||
result.record.brand ?? null,
|
||||
category,
|
||||
result.record.unitCost || null,
|
||||
result.score.salePrice,
|
||||
keepa?.avgPrice90 ?? null,
|
||||
keepa?.salesRank ?? null,
|
||||
keepa?.salesRankAvg90 ?? null,
|
||||
keepa?.sellerCount ?? null,
|
||||
keepa?.amazonIsSeller == null ? null : keepa.amazonIsSeller ? 1 : 0,
|
||||
keepa?.amazonBuyboxSharePct90d ?? null,
|
||||
keepa?.monthlySold ?? null,
|
||||
keepa?.salesRankDrops30 ?? null,
|
||||
keepa?.salesRankDrops90 ?? null,
|
||||
result.upc,
|
||||
result.score.fbaFee,
|
||||
spApi?.fbmFee ?? null,
|
||||
spApi?.referralFeePercent ?? null,
|
||||
result.score.score,
|
||||
result.score.profit,
|
||||
result.score.margin,
|
||||
result.score.roi,
|
||||
result.score.reason,
|
||||
result.lookup.status,
|
||||
result.lookup.reason ?? null,
|
||||
result.lookup.candidateAsins.join(","),
|
||||
canSell,
|
||||
spApi?.sellabilityStatus ?? null,
|
||||
spApi?.sellabilityReason ?? null,
|
||||
result.score.verdict,
|
||||
Math.round(result.score.score),
|
||||
result.score.reason,
|
||||
result.fetchedAt,
|
||||
);
|
||||
}
|
||||
})();
|
||||
}
|
||||
|
||||
export function refreshRunCountsInDb(dbPath: string, runId: number): RunCounts {
|
||||
const database = getDb(dbPath);
|
||||
const stats = database
|
||||
|
||||
Reference in New Issue
Block a user