Refactor supplier analysis and product handling

- Updated `SupplierAnalysisResult` to include a `product` field and modified related tests.
- Refactored `addRowsSheet` to accommodate changes in the product structure.
- Enhanced UPC file analysis to utilize a new `toSupplierInputRecord` function for cleaner record creation.
- Introduced new types for supplier input records and product observations.
- Updated frontend components to handle new product details and analysis history.
- Improved database writing functions to streamline run completion and error handling.
- Added new API endpoints for product details and adjusted routing in the frontend.
This commit is contained in:
Victor Noguera
2026-05-25 12:27:41 -04:00
parent c006d87c54
commit 923ebbaec5
33 changed files with 2536 additions and 4872 deletions

View File

@@ -155,7 +155,7 @@ ranked sourcing workbook:
2. Resolves UPCs to ASINs with SP-API catalog lookup first, then falls back to Keepa for no-match/request-failure cases.
3. Enriches resolved ASINs with Keepa demand/competition data and SP-API sellability + FBA fees.
4. Scores products with deterministic BUY/WATCH/SKIP logic; this path does not call LM Studio.
5. Writes a ranked Excel workbook and persists rows into the existing `runs` + `results` tables.
5. Writes a ranked Excel workbook and persists rows through unified runs, UPC resolution, product observation, and scoring-history tables.
CLI usage:
@@ -244,20 +244,28 @@ Numeric parsing accepts plain numbers as well as formatted values like `$12.50`,
4. **Keepa fetch** — batch the sellable (uncached) ASINs in a single API call (up to 100 per request)
5. **Enrich** — fetch SP-API pricing + FBA/FBM fees for sellable ASINs; combine with Keepa data and spreadsheet data
6. **LLM analysis** — send batches of 5 sellable products to LM Studio for FBA/FBM/SKIP verdict; skipped ASINs get auto-SKIP verdict (confidence 100) and bypass LLM entirely
7. **Output** — print results table to console (includes all ASINs), optionally write CSV/XLSX, and **persist results to a SQLite database**.
7. **Output** — print results table to console (includes all ASINs), optionally write CSV/XLSX, and persist products, observations, run items, and analysis revisions to PostgreSQL.
## Persistent Storage with SQLite
## Persistent Storage
Results from each run are now stored in a SQLite database named `db/results.db` by default. The SQLite implementation details are handled in `src/database.ts`. This allows you to:
PostgreSQL persistence is managed with Drizzle in `src/db/schema.ts` and `src/db/persistence.ts`. ASINs are canonical product identities: all inputs normalize to uppercase 10-character alphanumeric keys before any product reference is stored.
- Revisit past analysis results.
- Query and analyze historical data.
- Track product performance over time.
Core tables:
The database will automatically be created if it doesn't exist. Two tables are created:
- `products`: one canonical row per ASIN with latest descriptive metadata.
- `product_observations`: append-only marketplace, pricing, fee, and sellability snapshots.
- `runs` and `run_items`: unified lifecycle/history for lead, category, supplier UPC, and stalker workflows.
- `analysis_revisions` and `supplier_scores`: append-only analysis results; reanalysis does not overwrite prior decisions.
- `sourcing_inputs`, `upc_resolutions`, and `product_identifiers`: source-row and confirmed identifier data kept separate from catalog products.
- `stalker_run_details`, `stalker_scans`, and `stalker_inventory_items`: seller workflow provenance linked back to products and observations.
- `runs`: Stores metadata about each analysis run (timestamp, input file, output file, and summary counts).
- `results`: Stores detailed analysis results for each product from each run, linked to the `runs` table.
Unresolved or ambiguous supplier UPCs stay on their run item and resolution records; a UPC is never stored as an ASIN.
Web endpoints use unified identifiers:
- `GET /api/runs`, `GET /api/runs/:runId`, `GET /api/runs/:runId/items`
- `GET /api/products`, `GET /api/products/:asin`
- `POST /api/run-items/:itemId/reanalyze`
## Output columns