Skip to content

1.8.10

βš™οΈ Patch 1.8.10 β€” FBA OOS buy-price recalc, full Sellerlogic sync & user guide

πŸš€ Summary

  • Buy-price changes on OOS FBA articles β€” force recalc and Sellerlogic export now run even when stock is 0 (min/max bounds stay correct while out of stock).
  • Base cron FBA sync β€” imports the full Sellerlogic product list (new articles + new marketplaces), not only stock/dimension updates on existing rows.
  • Buy-price lookup β€” shopping_table match also tries the article’s FBA ASIN when the base SKU differs.
  • Documentation β€” new Multi-Repricer User Guide (UI-focused: statuses, skips, workflows, errors).
  • Health audit β€” /health endpoints + repricer_health_audit cron + UI config (Base Articles β†’ Health) for early detection of stale EK sync / missing locals.
  • Sentry β€” optional error tracking for all backend services (enabled by SENTRY_DSN) and the React frontend (enabled by VITE_SENTRY_DSN). Added a Sentry navigation link next to Grafana in the sidebar.
  • Prometheus β€” new GET /metrics (public) on service-multi-repricer + Prometheus service in compose to scrape it.
  • Otto recalc bootstrap β€” articles missing min_price or max_price get standard min/max calculated on recalc, then max price is pushed to Otto + Plenty as the sale price.
  • Otto buy-price change export β€” when the base cron detects a shopping-table EK change, Otto force recalc also pushes the new max price to Otto + Plenty as the sale price (same push path as bootstrap).
  • Observability debug β€” Debug β†’ Observability page to test Sentry (frontend + backend) and Prometheus counters.

✨ Improvements

FBA β€” buy price change while OOS

Before After
OOS SKUs excluded from buy-price force recalc OOS included (UVP articles still excluded)
FBA recalc always skipped when status = OOS Skipped on normal recalc; runs on force recalc (force_min_max)
Sellerlogic min/max stale after EK change on OOS items Recalc β†’ UPDATE_NEEDED β†’ export on next cron/export

Typical symptom fixed: buy price updated in shopping table (e.g. 03.07.2026) but Sellerlogic β€œUpdated min/max bounds” unchanged since an older date while the article was OOS.

FBA β€” full sync during base repricer cron

Before After
sync_base_articles=False β€” stock/dims only on existing FBA rows sync_base_articles=True β€” full Sellerlogic product fetch
Articles only in Sellerlogic not imported by cron New Sellerlogic products create base article + FBA detail (SKU = ASIN)
New Amazon marketplace on existing SKU not added New marketplace merged into international_pricing (if marketplace ID is known)

Buy prices β€” ASIN fallback

sync_buy_prices lookup order:

  1. repricer_articles.sku β†’ shopping_table.asin_sku
  2. If missing β†’ fba_details.asin β†’ shopping_table.asin_sku

Helps when Plenty SKU β‰  shopping-table ASIN but FBA ASIN is set.

Otto β€” bootstrap min/max + sale price export

Before After
Otto article with no min/max stored β†’ recalc only refreshed profit/margin fields Recalc computes and stores min/max using standard margin + provision rules
No automatic price push for new/incomplete Otto rows max_price is sent to Otto API and Plenty (otto channel) as the sale price
use_min_max_rules could stay off on incomplete rows Enabled automatically when bounds were missing
Buy-price change in base cron β†’ min/max recalculated but sale price unchanged Force recalc also sets sale_price = max_price and pushes to Otto + Plenty

When it runs:

  1. Missing bounds β€” any Otto recalculate_articles pass (manual Recalculate All, Otto cron step 2, base sync recalc) when either min_price or max_price was NULL before recalc.
  2. Buy-price change β€” base cron force_recalc_channels_for_buy_price_change (non-UVP SKUs where shopping_table EK actually changed). Otto recalc runs with export_max_sale_price=True.

Plenty mapping: sale price = max_price, list/strike price = max_price + 10 (same pattern as manual change-price).

Observability β€” Sentry + Prometheus test tooling

Area What was added
Frontend Debug β†’ Observability (Sentry / Prometheus) β€” trigger client errors, backend crash (1/0), custom logger.error, capture_message, Prometheus test counter
Backend GET/POST /api/v1/multi/health/debug/* endpoints (JWT required)
Logging Custom backend_logging errors on multi-repricer now attach a Sentry handler (loggers use propagate=False)

Scope today: Sentry is wired for frontend + all backend services. Prometheus now scrapes /metrics from service-multi-repricer + service-invoice/jtl/plenty/tickets/omni (request metrics).

Multi-repricer (backend)

  • app/api/v1/endpoints/repricer_articles.py β€” OOS force recalc; FBA full sync; ASIN buy-price fallback; Otto export_max_sale_price on buy-price force recalc
  • app/api/v1/endpoints/fba_articles.py β€” FBA recalc allows OOS when force_min_max=True
  • app/api/v1/endpoints/otto_articles.py β€” missing min/max bootstrap + buy-price-change export to Otto/Plenty; shared push_otto_sale_price_to_channels helper; export_max_sale_price flag on recalculate_articles
  • app/api/v1/endpoints/health.py β€” health audit config endpoints + Discord alerts + Prometheus metrics + debug/test endpoints
  • app/main.py β€” Sentry init (optional, with logging handler), public /metrics, health audit cron defaults (48h threshold)
  • app/tests/test_force_recalc_resolution.py β€” OOS included in force recalc
  • app/tests/test_recalculate_channels.py β€” OOS + force_min_max FBA test; Otto missing min/max bootstrap test; Otto buy-price-change export test

Frontend

  • src/pages/MultiRepricer/Tabs/BaseArticles/BaseArticles.jsx β€” Health button + audit config dialog
  • src/pages/Temp_Pages/observability.jsx β€” Observability debug page (Sentry / Prometheus tests)
  • src/services/api/multi/debug.js β€” API client for debug endpoints
  • src/layouts/DashboardLayout/index.jsx β€” sidebar Sentry link (next to Grafana)
  • src/main.jsx β€” optional Sentry init (enabled by VITE_SENTRY_DSN)
  • package.json β€” add @sentry/react

Documentation

  • docs/docs/services/service_multi_repricer/user_guide.md β€” end-user guide (new)
  • docs/docs/services/service_multi_repricer/index.md β€” link to user guide
  • docs/mkdocs.yml β€” nav entry
  • docs/docs/services/service_multi_repricer/endpoints/health.md β€” health/audit endpoints
  • docs/docs/infrastructure/prometheus.md β€” Prometheus setup + Grafana datasource + debug page notes
  • docs/docs/infrastructure/grafana_promtail.md β€” Grafana/Loki/Promtail overview (added)
  • docker/prometheus/config.yml β€” scrape config (directory mount, not single-file bind)

πŸ”§ Deploy

  1. Rebuild / restart service-multi-repricer (backend code only).
  2. Rebuild / restart frontend (Sentry + sidebar link).
  3. Rebuild docs container or redeploy docs site if you publish patchnotes from the repo.
  4. No database migration.

πŸ”§ Prometheus (optional)

  • Prometheus service is added in docker-compose.yml and docker-compose-portainer.yml.
  • Config directory: docker/prometheus/ (file: config.yml)
  • Scrapes: service-multi-repricer:8001/metrics

If Prometheus fails on Portainer with a mount error, see Prometheus troubleshooting (usually a missing config file created as a directory on the host).

  • Grafana datasource URL (inside docker network): http://prometheus:9090

πŸ”§ Sentry configuration (optional)

Backend (service-multi-repricer):

  • SENTRY_DSN (required to enable)
  • SENTRY_ENVIRONMENT (default production)
  • SENTRY_RELEASE (optional)
  • SENTRY_TRACES_SAMPLE_RATE (default 0.0)

Frontend (React / Vite):

  • VITE_SENTRY_DSN (required to enable)
  • VITE_SENTRY_ENVIRONMENT (default production)
  • VITE_SENTRY_RELEASE (optional)
  • VITE_SENTRY_TRACES_SAMPLE_RATE (default 0)
  • VITE_SENTRY_URL (optional) β€” used for the sidebar link (defaults to the org settings URL if unset)

⚠️ Vite dev / node_modules volume note: if your frontend container uses a persistent /app/node_modules volume, you may need to recreate the container or run npm install inside it after updating dependencies.

Optional one-off after deploy β€” recalc + export a single OOS SKU:

POST /api/v1/multi/repricer-articles/sync/B0054J6WPE?update_prices=true

Or use Base Articles β†’ Sync with Update Prices checked.

βœ… Verify

  1. Pick an OOS FBA article; change buy price in shopping table β†’ run base sync with Update Prices β†’ status becomes UPDATE_NEEDED β†’ export updates Sellerlogic min/max.
  2. Add a product in Sellerlogic only β†’ next base cron creates it locally (base + FBA tab).
  3. Docs: open Multi-Repricer Service β†’ User Guide in the documentation site.
  4. Otto: pick an article with empty min/max β†’ Recalculate All β†’ min/max filled, sale price pushed (check Otto + Plenty).
  5. Otto buy-price change: change EK in shopping table β†’ run base Sync All β†’ Otto force recalc pushes new max as sale price (check Otto + Plenty).
  6. Sentry: open Debug β†’ Observability β†’ run Logger error or Crash β†’ event appears in Sentry (if DSN set).
  7. Prometheus: same debug page β†’ Prometheus test counter β†’ query repricer_debug_test_total on /metrics.

⚠️ Notes

  • FBM still skips OOS on recalc (unchanged).
  • UVP articles still skip buy-price force recalc by design.
  • Unknown Amazon marketplace IDs are logged and skipped until added to the hardcoded region_map in fba_articles.py.
  • UK marketplace: sync stores region as UK; SP-API recalc expects GB β€” UK may import from Sellerlogic but not recalc via Amazon fees until mapping is aligned.
  • Otto export (bootstrap or buy-price change) requires active Otto + Plenty credentials and Plenty article/variant IDs on the base article.
  • Otto buy-price export runs only on the force-recalc pass after a real EK delta β€” not on every base sync when the buy price is unchanged.
  • Prometheus request metrics are now exposed on service-invoice, service-jtl, service-plenty, service-tickets, and service-omni via GET /metrics, and Prometheus scrape targets were updated accordingly.