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:
71
src/types.ts
71
src/types.ts
@@ -26,23 +26,24 @@ export interface ProductRecord {
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
export interface KeepaData {
|
||||
currentPrice: number | null;
|
||||
avgPrice90: number | null;
|
||||
minPrice90: number | null;
|
||||
maxPrice90: number | null;
|
||||
export interface KeepaData {
|
||||
currentPrice: number | null;
|
||||
avgPrice90: number | null;
|
||||
minPrice90: number | null;
|
||||
maxPrice90: number | null;
|
||||
salesRank: number | null;
|
||||
salesRankAvg90: number | null;
|
||||
salesRankDrops30: number | null;
|
||||
salesRankDrops90: number | null;
|
||||
sellerCount: number | null;
|
||||
amazonIsSeller: boolean | null;
|
||||
amazonBuyboxSharePct90d: number | null;
|
||||
buyBoxSeller: string | null;
|
||||
buyBoxPrice: number | null;
|
||||
monthlySold: number | null;
|
||||
categoryTree: string[];
|
||||
}
|
||||
amazonBuyboxSharePct90d: number | null;
|
||||
buyBoxSeller: string | null;
|
||||
buyBoxPrice: number | null;
|
||||
buyBoxAvg90?: number | null;
|
||||
monthlySold: number | null;
|
||||
categoryTree: string[];
|
||||
}
|
||||
|
||||
export type KeepaUpcLookupStatus =
|
||||
| "found"
|
||||
@@ -51,15 +52,17 @@ export type KeepaUpcLookupStatus =
|
||||
| "multiple_asins"
|
||||
| "request_failed";
|
||||
|
||||
export interface KeepaUpcLookupDetail {
|
||||
requestedUpc: string;
|
||||
normalizedUpc: string;
|
||||
status: KeepaUpcLookupStatus;
|
||||
export interface KeepaUpcLookupDetail {
|
||||
requestedUpc: string;
|
||||
normalizedUpc: string;
|
||||
status: KeepaUpcLookupStatus;
|
||||
asin: string | null;
|
||||
candidateAsins: string[];
|
||||
keepaData: KeepaData | null;
|
||||
reason?: string;
|
||||
}
|
||||
reason?: string;
|
||||
}
|
||||
|
||||
export type UpcLookupDetail = KeepaUpcLookupDetail;
|
||||
|
||||
export type SellabilityInfo = {
|
||||
canSell: boolean | null;
|
||||
@@ -88,10 +91,36 @@ export interface LlmVerdict {
|
||||
reasoning: string;
|
||||
}
|
||||
|
||||
export interface AnalysisResult {
|
||||
product: EnrichedProduct;
|
||||
verdict: LlmVerdict;
|
||||
}
|
||||
export interface AnalysisResult {
|
||||
product: EnrichedProduct;
|
||||
verdict: LlmVerdict;
|
||||
}
|
||||
|
||||
export type SupplierVerdict = "BUY" | "WATCH" | "SKIP";
|
||||
|
||||
export interface SupplierScore {
|
||||
salePrice: number | null;
|
||||
fbaFee: number | null;
|
||||
profit: number | null;
|
||||
margin: number | null;
|
||||
roi: number | null;
|
||||
demandScore: number;
|
||||
competitionPenalty: number;
|
||||
score: number;
|
||||
verdict: SupplierVerdict;
|
||||
reason: string;
|
||||
}
|
||||
|
||||
export interface SupplierAnalysisResult {
|
||||
upc: string;
|
||||
rowNumber?: number;
|
||||
record: ProductRecord;
|
||||
lookup: UpcLookupDetail;
|
||||
keepa: KeepaData | null;
|
||||
spApi: SpApiData | null;
|
||||
score: SupplierScore;
|
||||
fetchedAt: string;
|
||||
}
|
||||
|
||||
export interface CategoryRunSummaryDb {
|
||||
categoryId: number;
|
||||
|
||||
Reference in New Issue
Block a user