Skip to content

1.7.3

βš™οΈ Patch 1.7.3 β€” Buy-price force recalc, repricer test suite, and deprecation cleanup

πŸš€ Summary

  • Repricer base cron now detects actual buy_price changes from shopping_table and runs a forced min/max recalculation + export for affected articles β€” even when use_min_max_rules is disabled on a channel.
  • UVP articles (min_uvp / max_uvp set) are excluded from this flow; article_type is reset on eligible buy-price changes so Penner classification can be re-evaluated.
  • FBM/FBA export in the cron path still respects per-region ignore flags (no force=True β€” unlike the UVP export flow).
  • Added a 39-test pytest suite covering buy-price sync, force-recalc selection, per-channel recalc, exports, and the full cron recalc/export pipeline.
  • Cleaned up Pydantic v2 / SQLAlchemy 2.0 deprecations and test-time ResourceWarning noise.

✨ Improvements

  • Buy-price sync (sync_buy_prices):
  • Returns a new changed list (SKUs where brutto_buy_price actually changed), separate from success (confirmed/updated without error).
  • Force recalc after buy_price change (_sync_articles_internal):
  • After the normal full recalc pass, runs a second pass per eligible SKU with force_min_max=True on Shopify, Kaufland, Otto, FBM, and FBA.
  • Helper _resolve_buy_price_force_recalc_skus centralises selection: skips UVP and OOS (stock == 0), resets article_type to null for included SKUs.
  • Per-channel force_min_max flag on recalculate_articles:
  • When True, recalculates and writes min/max (or Shopify price) even if use_min_max_rules is false β€” without permanently flipping that flag.
  • Manual-override path (profit-only refresh) remains the default when buy_price is unchanged.
  • Test suite (service_multi-repricer/app/tests/) β€” 39 tests, no Docker/Postgres required:
  • test_sync_buy_prices.py β€” change detection, missing shopping rows, newest row wins.
  • test_force_recalc_resolution.py β€” UVP/OOS exclusion, article_type reset, mixed batches.
  • test_recalculate_channels.py β€” base vs force_min_max for all channels; OOS skip; FBM/FBA manual override vs SP-API full recalc.
  • test_exports.py β€” Shopify/Kaufland export success; FBM/FBA ignore respected; UVP-style force=True bypasses ignore.
  • test_cron_sync_flow.py β€” end-to-end _sync_articles_internal with mocked sync steps.
  • In-memory SQLite fixtures; external APIs (Plenty, Sellerlogic, Kaufland, SP-API) mocked.
  • pytest configuration:
  • pytest.ini: pythonpath = app .. so tests run from the service folder without manual PYTHONPATH (picks up backend_logging).
  • error::ResourceWarning β€” unclosed SQLite connections fail tests; SQLModel-internal Pydantic deprecation filtered until library upgrade.
  • Deprecation / hygiene:
  • Settings uses SettingsConfigDict; response/SQLModel schemas migrated from nested class Config to model_config = ConfigDict(...).
  • sqlalchemy.orm.declarative_base instead of deprecated sqlalchemy.ext.declarative.
  • Kaufland export/sync timestamps use Europe/Berlin instead of datetime.utcnow().
  • Plenty_Manager.batch_get_stock typing fixed for Python 3.13+ (List[tuple[int, int]]).

πŸ› Bug Fixes

  • Buy_price sync false positives: SKUs were treated as β€œchanged” whenever sync succeeded, even if the price was identical β€” changed is now only populated on a real delta.
  • Manual-override articles stuck after EK change: cron recalc refreshed profit on fixed target prices but did not recompute bounds when use_min_max_rules=false β€” force pass fixes that for buy_price changes only.
  • Penner article_type stale after EK change: eligible articles get article_type = null on buy_price update so classification can be reassigned.

πŸ“ Files changed

Backend (service_multi-repricer)

  • app/api/v1/endpoints/repricer_articles.py β€” buy_price changed tracking, _resolve_buy_price_force_recalc_skus, force recalc loop in cron background task.
  • app/api/v1/endpoints/shopify_articles.py β€” force_min_max on recalculate.
  • app/api/v1/endpoints/kaufland_articles.py β€” force_min_max, Berlin timestamps on export/sync.
  • app/api/v1/endpoints/otto_articles.py β€” force_min_max on recalculate.
  • app/api/v1/endpoints/fbm_articles.py β€” force_min_max on recalculate.
  • app/api/v1/endpoints/fba_articles.py β€” force_min_max on recalculate.
  • app/services/plenty/plenty_manager.py β€” batch_get_stock type annotation fix.
  • app/core/config.py, app/core/database.py, app/models/base.py β€” ConfigDict / declarative_base.
  • app/models/*.py, app/schemas/*.py β€” Pydantic ConfigDict migration (models/schemas touched by tests and exports).

Tests

  • app/tests/conftest.py, app/tests/test_*.py (5 modules), app/tests/__init__.py.
  • pytest.ini.

πŸ”§ Database & SQL

  • No schema migration required.
  • article_type may be set to NULL on repricer articles when shopping_table reports a new buy_price (non-UVP, in-stock articles only).

Usage notes

  • Run tests locally from backend/service_multi-repricer:
    pip install -r requirements.txt pytest pytest-asyncio
    python -m pytest app/tests
    
    No running Docker stack needed β€” tests use in-memory SQLite and mocked marketplace APIs.
  • After deploy, the base repricer cron will automatically force-recalc and export channels when EK changes; UVP-managed articles are untouched.
  • FBM/FBA regions with ignore !== false are still skipped on cron export; only the dedicated UVP export path uses force=True.
  • Otto min/max are updated in DB on force recalc; Otto live price push still goes through the separate Otto monitor cron (unchanged).