Skip to content

Multi-Repricer Service

Purpose

The Multi-Repricer Service is the pricing intelligence engine of the platform. It continuously monitors competitor prices on marketplaces (primarily Otto and Kaufland) and dynamically adjusts listing prices to maximize sales while preserving profit margins.

High-Level Architecture

The service runs as a Docker container (service-multi-repricer) exposing an API on port 8005.

  • Inputs:
  • Competitor Data: Scraped via proxies or fetched via APIs.
  • Cost Data: Buy prices, shipping costs, and fees.
  • Rules: User-defined margin and profit constraints.
  • Outputs:
  • Price Updates: Pushed to Otto/Kaufland APIs.
  • Analytics: Price history and buybox status logged to the database.

Database Schema

MonitorItemDB (item_monitor)

The central registry for all tracked articles.

  • Key Fields: sku, my_price, site_price (competitor), min_price, max_price, is_in_buybox.
  • State: Items can be active, paused, or error.

MarginRule (otto_margin_rules)

Defines the profitability guardrails.

  • Logic: "If I buy for X, I need at least Y% margin OR Z€ absolute profit."
  • Fields: min_margin, min_min_profit, max_margin, max_min_profit.

PackageMapping (package_mappings)

Maps product weight to shipping costs.

  • Example: 0-200g -> "XS-Paket" (3.50€).
  • Usage: Used to calculate the "Break-Even Price".

Proxy (proxies) & WebshareCredentials

Manages the infrastructure for anonymous scraping.

  • Proxies: Rotated to avoid IP bans.
  • Webshare: External provider for residential proxies.

Pricing Logic (Kaufland & Otto)

The service uses a sophisticated formula to determine the Minimum Selling Price ($P_{min}$).

1. The Formula

$$ P{min} = \max(P) $$}, P_{profit

Where:

  • $P_{margin}$: Price required to hit the target margin %.
  • $P_{profit}$: Price required to hit the minimum absolute profit (e.g., 3€).

2. Cost Components

The calculation accounts for:

  • VAT: Value Added Tax (19%).
  • Marketplace Fees: Variable % + Fixed Fee per item.
  • Shipping: Derived from PackageMapping based on weight.
  • Buy Price: Net cost of goods.

3. Repricing Strategy

  1. Check Competitor: Look at next_competitor_price.
  2. Undercut: If competitor > $P_{min}$, set price to Competitor - 0.01€.
  3. Floor: If competitor < $P_{min}$, set price to $P_{min}$ (do not sell at a loss).
  4. Buybox: If we already have the buybox, potentially raise the price to test elasticity.

Application Structure

  • app.py: Entry point.
  • routers/:
  • otto_repricer_router.py: Manages the repricing loop for Otto.
  • kaufland_router.py: Manages the repricing loop for Kaufland.
  • proxies_router.py: API for managing the proxy pool.
  • core/:
  • pricing_engine.py: (Conceptual) Shared logic for price calculations.

Key Workflows

1. The Repricing Loop

graph TD Cron[Cron Job] -->|Start| Fetch[Fetch Articles] Fetch -->|Loop SKUs| Scrape[Get Competitor Price] Scrape -->|Success| Calc[Calculate Min/Max Price] Calc -->|Apply Rules| Decision{Undercut?} Decision -->|Yes| NewPrice[Set Price = Comp - 0.01] Decision -->|No| NewPrice[Set Price = Min Price] NewPrice -->|Update DB| DB[(Postgres)] NewPrice -->|Push API| Market[Marketplace API]

2. Proxy Management

To ensure reliable scraping, the service maintains a pool of proxies.

  • Health Checks: Periodically tests proxies against a target URL.
  • Rotation: Fails over to the next proxy if a request fails.
  • Webshare Sync: Automatically pulls new proxies from the Webshare API.

Technical Details

Rate Limiting & Concurrency

  • Marketplace APIs: Strict rate limits are enforced (e.g., Otto allows X req/sec). The service uses internal throttles to respect these.
  • Scraping: Distributed across multiple proxies to avoid detection.

Error Handling

  • Price Guards: Sanity checks prevent setting prices to 0.01€ or absurdly high values.
  • Fallback: If scraping fails, the item retains its last known safe price.