1.8.3
βοΈ Patch 1.8.3 β Wholesale catalog price, Keepa analyze/margin, push batching¶
π Summary¶
- Catalog price column β lowest in-stock wholesale offer across all suppliers in
wholesale_shopping_list(Jadro, Rney, Qogita, β¦) with seller and stock; backup when live Qogita Price is empty. - Target EK aligned with Amazon Revenue Calculator Nettospanne (10% = profit Γ· VK brutto at
avg90_new_price_cents). - Analyze by EAN re-runs on already-analyzed rows, batches with offset pagination (no infinite loop), ~1s per 500 rows (single DB commit, no per-row API calls).
- Keepa pipeline β 10k ASIN cap, fetch skip statuses, 429 β token wait; push batches 200 per call.
- Watchlist cron β catalog flag sync + Discord when rows wrongly marked Not in catalog.
- Otto repricer β
recalculate_articlesre-activates paused articles when min/max change.
β¨ Improvements¶
Wholesale catalog price (all suppliers)¶
wholesale_offers.pyβ lowest price with stock > 0 across all supplier columns.- API fields:
wholesale_best_price,wholesale_best_stock,wholesale_best_seller. - Frontend β Catalog price column (price, seller, stock).
- Push to Qogita still requires Qogita catalog (
qogita_preis/qogita_bestand); other wholesalers are sourcing backup only.
Suppliers: Jadro, Rney, Polarmoda, Parfum Wholesales, Engelsa, B2B Luxury, Nunu, Parfumtrend, Qogita, Novaengel, Naypes.
Target EK β Amazon Nettospanne margin¶
Problem: Target EK used margin on net revenue (VK Γ· 1.19). Amazonβs calculator shows Nettospanne = profit Γ· VK brutto β so 10% target looked like ~8.4% in Seller Central (e.g. VK β¬28.69, fees β¬7.88, EK β¬13.82 β 8.39% Nettospanne).
Formula (VK = avg90_new_price_cents / 100):
VK_netto = VK_brutto / 1.19
profit_target = VK_brutto Γ margin%
EK = VK_netto β Amazon fees β profit_target
Example: VK β¬28.69, fees β¬7.88, margin 10% β target EK β¬13.36 (not β¬13.82). VAT β¬4.58 is computed correctly; fees unchanged.
- UI: Margin % (Nettospanne), column Target EK (10% Nettospanne).
compute_margin_breakdown()β logs/comparemargin_on_gross_vk_pct(Amazon) vsmargin_on_net_revenue_pct.
Analyze by EAN β reanalyze, speed, batching¶
reanalyze: trueβ recomputes EK on rows that already havekeepa_scanned_at(needed after margin formula changes).- Offset pagination β
ORDER BY gtin+offset/limit; API returnsreanalyze_total,reanalyze_next_offset,reanalyze_complete(fixes endless 500-row loops fromupdated_atcursor). - Performance β one
commit()per batch; catalog EAN keys loaded once; skip DB write when EK/margin/catalog flag unchanged (ek_skipped_write). - Logging β batch start/complete only with
duration_ms,ek_changed,ek_skipped_write(no per-GTIN lines). - Frontend loops until
reanalyze_complete(~3 batches for 1384 items at 500/batch).
Push batching¶
- Default 200 per call (
QOGITA_PUSH_BATCH_SIZE); frontend loops until queue drained.
Watchlist cron β catalog flag correction¶
- After Qogita sync:
sync_watchlist_catalog_flags()+ Discord alert for corrected Not in catalog rows.
Keepa pipeline & query¶
- Finder selection update (
perPage50,categories_include, β¦). - 10k ASIN page cap;
keepa_fetch_statusfor skipped no-EAN / no-product / analyze rows. - 429 β
waiting_tokens, notfailed.
Analyze & watchlist UI¶
- Status filters/chips for Keepa skipped rows; GTIN / ASIN β
amazon.de. - Recompute fees when
total_fees_eurmissing;skipped_analyzefor unanalyzable rows.
DB sync¶
- Preset
qogitasyncswholesale_shopping_list+qogita_watchlist_items.
.\scripts\db-sync\sync-from-prod.ps1 -Preset qogita
Otto repricer (service_multi-repricer)¶
- Min/max recalc β
status=active,unpause_date=null.
π Bug Fixes¶
Analyze did not update existing rows¶
analyze_productsonly queuedkeepa_scanned_at IS NULL; margin changes had no effect until reanalyze mode.
Analyze infinite / slow batches¶
- ~16s/500 rows β per-row
commit()+ per-GTIN catalog SQL (no Keepa API). - Infinite loop β
updated_atrotation re-selected the same 500 rows; fixed with offset +reanalyze_complete.
Stale βNot in catalogβ¶
- Analyze uses DB catalog lookup; cron + list API enrich from
wholesale_shopping_list.
Keepa fetch token waste¶
skipped_no_ean/skipped_no_productβ no repeat fetch on stub ASINs.
β¨ Tests¶
test_wholesale_offers.pyβ supplier selection.test_keepa_pricing.pyβ Amazon Nettospanne EK (β¬28.69 β β¬13.36), margin breakdown.test_keepa_pipeline.py,test_keepa_scanner_mocked.pytest_recalculate_channels.pyβ Otto min/max β active.
cd backend/service_omni
pytest app/tests/test_wholesale_offers.py app/tests/test_keepa_pricing.py app/tests/test_keepa_pipeline.py -v
cd backend/service_multi-repricer
pytest app/tests/test_recalculate_channels.py -v -k "min_max_change"
π Files changed¶
Backend (service_omni)
app/services/qogita/wholesale_offers.py,watchlist_present.py,constants.pyapp/crud/qogita_catalog.py,qogita.pyapp/services/keepa/scanner.py,pipeline_runner.py,constants.py,pricing.pyapp/services/price_alerts/watchlist_cron.py,discord_notifications.pyapp/api/v1/endpoints/qogita.py,keepa.pyapp/models/qogita.py,keepa.pyapp/tests/test_wholesale_offers.py,test_keepa_pricing.py,test_keepa_pipeline.py,test_keepa_scanner_mocked.py
Backend (service_multi-repricer)
app/api/v1/endpoints/otto_articles.pyapp/tests/test_recalculate_channels.py
Frontend
src/pages/Statistics/Tabs/QogitaWatchlistTab.jsx,qogitaWatchlistPrefs.js
Postgres
docker/postgres/migrations/add_keepa_fetch_status.sqldocker/postgres/tables/qogita_watchlist_items.sql
Scripts
scripts/db-sync/tables.json
π§ Database & deploy¶
\i docker/postgres/migrations/add_keepa_fetch_status.sql
Restart service-omni, service_multi-repricer. Rebuild frontend.
QOGITA_PUSH_BATCH_SIZE=200
Usage notes¶
Catalog price vs Qogita price
| Column | Source | When populated |
|---|---|---|
| Catalog price | Best wholesale offer with stock | Any supplier in wholesale_shopping_list |
| Qogita Price | Qogita watchlist API | After push + sync (qid set) |
Target EK vs Amazon calculator
- Set Margin % (Nettospanne) (e.g. 10).
- Analyze by EAN β runs full reanalyze pass once (~3Γ500 for ~1400 items).
- Spot-check in Seller Central: COGS = Target EK, VK = avg90 price; Nettospanne should match margin %.
Analyze logs (expected)
Keepa analyze batch start: offset=0 requested=500 reanalyze_total=1384
Keepa analyze batch complete: reanalyze_next_offset=500 reanalyze_complete=false duration_ms=~1000
β¦
Keepa analyze batch complete: reanalyze_next_offset=1384 reanalyze_complete=true
After margin or formula deploy: run Analyze by EAN once so all calculated_ek_price / target_price values refresh.
Local prod data
.\scripts\db-sync\sync-from-prod.ps1 -Preset qogita