export interface ProductRecord { asin: string; name: string; unitCost: number; brand?: string; category?: string; amazonRank?: number; avgPrice90FromSheet?: number; sellingPriceFromSheet?: number; fbaNet?: number; grossProfit?: number; grossProfitPct?: number; netProfitFromSheet?: number; roiFromSheet?: number; moq?: number; moqCost?: number; totalQtyAvail?: number; link?: string; asinLink?: string; sourceUrl?: string; supplier?: string; promoCouponCode?: string; notes?: string; leadDate?: string; [key: string]: unknown; } 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; buyBoxAvg90?: number | null; monthlySold: number | null; categoryTree: string[]; } export type KeepaUpcLookupStatus = | "found" | "invalid_upc" | "not_found" | "multiple_asins" | "request_failed"; export interface KeepaUpcLookupDetail { requestedUpc: string; normalizedUpc: string; status: KeepaUpcLookupStatus; asin: string | null; candidateAsins: string[]; keepaData: KeepaData | null; provider?: "sp_api" | "keepa"; reason?: string; } export type UpcLookupDetail = KeepaUpcLookupDetail; export type SellabilityInfo = { canSell: boolean | null; sellabilityStatus: "available" | "restricted" | "not_available" | "unknown"; sellabilityReason?: string; }; export interface SpApiData extends SellabilityInfo { fbaFee: number; fbmFee: number; referralFeePercent: number; estimatedSalePrice: number; } export interface EnrichedProduct { record: ProductRecord; keepa: KeepaData | null; spApi: SpApiData; fetchedAt: string; } export interface LlmVerdict { asin: string; verdict: "FBA" | "FBM" | "SKIP"; confidence: number; reasoning: string; } 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: SupplierInputRecord; product: ProductRecord | null; lookup: UpcLookupDetail; keepa: KeepaData | null; spApi: SpApiData | null; score: SupplierScore; fetchedAt: string; } export interface SupplierInputRecord { name: string; unitCost: number; brand?: string; category?: string; } export interface Product { asin: string; name: string | null; brand: string | null; category: string | null; firstSeenAt: string; lastSeenAt: string; } export interface ProductObservation { id: number; productAsin: string; runId: number; source: string; fetchedAt: string; } export interface Run { id: number; type: | "lead_analysis" | "category_analysis" | "supplier_upc" | "stalker" | "stalker_analysis"; parentRunId?: number | null; status: string; } export interface RunItem { id: number; runId: number; productAsin: string | null; sourceRow?: number | null; } export interface AnalysisRevision { id: number; runItemId: number; decision: "FBA" | "FBM" | "BUY" | "WATCH" | "SKIP"; confidence: number | null; reasoning: string | null; analyzedAt: string; } export interface CategoryRunSummaryDb { categoryId: number; categoryLabel: string; runTimestamp: string; topAsinsChecked: number; availableAsins: number; fbaCount: number; fbmCount: number; skipCount: number; status: "ok" | "empty" | "failed"; errorMessage?: string; } export interface ProductAnalysisResultDb { asin: string; runId: number; name: string; brand?: string; category?: string; unitCost?: number; currentPrice?: number; avgPrice90d?: number; avgPrice90dSheet?: number; sellingPriceSheet?: number; salesRank?: number; salesRankAvg90d?: number; sellerCount?: number; monthlySold?: number; rankDrops30d?: number; rankDrops90d?: number; fbaFee?: number; fbmFee?: number; referralPercent?: number; canSell?: string; sellabilityStatus?: string; sellabilityReason?: string; verdict: string; confidence: number; reasoning?: string; fetchedAt: string; }