Make PriceCharting runs auditable and pin matches by product id

Two changes aimed at the first real run, since the integration cannot be
exercised here without a subscription.

Refresh now reports which product each game matched — name, console and the
source's id — next to the prices, and dry-run surfaces it before anything is
written. This is the failure that would otherwise go unnoticed: a lookup for
the DS "Chrono Trigger" resolving to the SNES original returns entirely
plausible numbers for the wrong game, and nothing in a bare price would say
so.

The matched id is then stored on the game, and later refreshes look it up
directly instead of repeating the title search. Cheaper, and stable — a
search that drifts to a different edition next month cannot silently
re-price something that was already matched correctly.

IPriceProvider takes an optional sourceId so this stays provider-agnostic.
eBay ignores it, having no stable per-product identifier in Browse.

139 backend tests.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-04 16:52:59 -04:00
co-authored by Claude Opus 5
parent 8e136f42f8
commit d34e6b4ced
10 changed files with 619 additions and 9 deletions
+28
View File
@@ -263,6 +263,34 @@ that copy's condition — so changing a condition re-prices it with no further
lookup. Every value carries the source that wrote it and the moment it was
captured.
**Using PriceCharting.** Subscribe, take the token from the Subscriptions page
("API/Download"), and set `PRICECHARTING_TOKEN` in `.env`. Their API access
comes with a paid subscription; the bulk CSV download is limited to their top
tier, so check which tier you need before subscribing — this integration does
per-game lookups and only needs the API.
Run a dry run first:
```bash
curl -X POST localhost:8080/api/prices/refresh \
-H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
-d '{"provider":"pricecharting","dryRun":true,"limit":10}'
```
The response reports **which product each game matched** — name, console and id
— alongside the prices. That matters more than it sounds: a lookup for the DS
"Chrono Trigger" that quietly resolves to the SNES original returns entirely
plausible numbers for the wrong game. Check the matches, then run without
`dryRun`.
Once a game is priced, the matched product id is stored and later refreshes look
it up directly, so they are cheaper and cannot drift to a different edition.
Their published API docs are not reachable without an account, so the response
parser follows the widely-used convention — integer pennies under hyphenated
keys — and is tolerant enough that a naming mismatch reads as "no price" rather
than throwing. `PriceChartingProvider.Parse` is the one place to adjust.
### Database changes
```bash