Skip to content

Plenty Service

Purpose

The Plenty Service acts as the central data warehouse and analytics engine for the Plentymarkets ERP system. Unlike simple connectors, this service maintains a historical record of all articles ("Snapshots"), enabling advanced analytics like "Penner/Renner" (Slow/Fast Mover) analysis, stock forecasting, and profitability tracking.

High-Level Architecture

The service runs as a Docker container (service-plenty) exposing an API on port 8003.

  • Integrations:
  • Plentymarkets API: Source of truth for products and orders.
  • Sellerboard: Imports profitability and sales reports.
  • Sellerlogic: (Legacy/Optional) Repricing data.
  • OpenAI: Used for generating product descriptions or translations (via openai_router).
  • Data Flow:
  • Ingest: Cron jobs fetch data from Plenty/Sellerboard.
  • Store: Data is versioned by date (snapshot_date) in Postgres.
  • Analyze: Rules are applied to identify underperforming products.

Database Schema

Article (plenty_articles)

Stores the state of a product at a specific point in time.

  • Key Fields: sku, plenty_id, name, stock_net, price, snapshot_date.
  • Concept: This table is append-only for history. To get the current state, queries filter by MAX(snapshot_date).

PennerRennerRule (penner_renner_rules)

Defines the criteria for classifying products.

  • Fields: days_sold_threshold, stock_turnover_threshold.
  • Usage: "If an item hasn't sold in X days and has > Y stock, it is a 'Penner' (Slow Mover)."

PlentyCredentials (plenty_credentials)

Stores API access tokens.

  • Fields: username, password, plenty_id, token.
  • Auth: Handles the login handshake and token refreshing.

Application Structure

  • app.py: Entry point.
  • routers/:
  • plenty_router.py: General API interactions.
  • plenty_article_router.py: Manages the snapshot lifecycle and cron jobs.
  • plenty_stock_router.py: Handles stock updates and syncs.
  • sellerboard_router.py: Parses CSV reports from Sellerboard.
  • openai_router.py: AI helper endpoints.

Key Workflows

1. Article Snapshotting

A daily Cron Job runs to capture the state of the entire inventory.

graph TD Cron[Daily Cron] -->|Trigger| Mgr[Plenty Manager] Mgr -->|Fetch Page 1| API[Plentymarkets API] API -->|Return Items| Mgr Mgr -->|Fetch Page N...| API Mgr -->|Transform| Models[Article Models] Models -->|Insert with Date| DB[(Postgres)]

2. Penner/Renner Analysis

This workflow identifies capital tied up in dead stock.

  1. Fetch Latest Snapshot: Get the current state of all items.
  2. Join Sales Data: Merge with Sellerboard sales history.
  3. Apply Rules:
    • Renner: High turnover, low days in stock.
    • Penner: Zero sales in last 90 days, high stock value.
  4. Report: Generate a list of items to discount or liquidate.

Technical Details

Snapshot Querying

Because the articles table grows indefinitely, querying the "current" state requires a specific SQL pattern:

SELECT * FROM plenty_articles
WHERE (sku, snapshot_date) IN (
    SELECT sku, MAX(snapshot_date)
    FROM plenty_articles
    GROUP BY sku
)

The service implements this via SQLAlchemy subqueries in get_latest_snapshots_query.

Rate Limiting

Plentymarkets has strict API limits (often bucket-based). The Plenty_Manager handles "429 Too Many Requests" responses by sleeping and retrying, ensuring large batch jobs (like full inventory downloads) complete successfully.