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.
2. Penner/Renner Analysis¶
This workflow identifies capital tied up in dead stock.
- Fetch Latest Snapshot: Get the current state of all items.
- Join Sales Data: Merge with Sellerboard sales history.
- Apply Rules:
- Renner: High turnover, low days in stock.
- Penner: Zero sales in last 90 days, high stock value.
- 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.