Skip to content

1.2.6

🚀 New Features

  • Added a debug page and backend endpoint to request, poll, and download Selling Partner API reports from Amazon.
  • Frontend: /debug/amazon/reports — form to request any SP-API report by reportType, marketplaceIds, optional dataStartTime/dataEndTime, and reportOptions JSON. The page downloads the resulting file automatically.
  • Backend: POST /reports/retrieve — unified server-side flow moved to services.amazon.spapi_client.fetch_report_document() which:
    1. creates the report via SP-API,
    2. polls until processing finishes (handles IN_QUEUE / IN_PROGRESSDONE / FATAL / CANCELLED),
    3. fetches report document metadata and downloads the document,
    4. decompresses GZIP payloads and returns the raw bytes.
  • Behavior: the server now content-sniffs the downloaded document and returns a .tsv (tab-separated) response for tab-delimited reports, .txt for other formats. The frontend derives the filename from the requested reportType (CORS hides Content-Disposition in some setups).
  • Notes: The frontend uses repeated marketplaceIds query params (via URLSearchParams.append) to satisfy FastAPI's List[str] parsing. reportOptions is sent as JSON body.
  • For Kaufland Articles Standard package of type "S-Paket" is selected if no weight can be found in plenty

🔧 Improvements

  • End-to-end maximum_price support for Kaufland articles:
  • Backend: maximum_price added to the update models so the API accepts and persists the field.
  • Frontend: "Max Price (€)" field added to the Kaufland article edit/create dialog and included in save flow (converted to cents).
  • DB: migration SQL added to create the maximum_price column when missing.

  • Reworked Otto product sync to use active-status as single source of truth:

  • Added get_active_status_bulk() to call GET /v5/products/active-status once (paginated) and produce a SKU->active boolean map.
  • Sync endpoint now performs a diff-first algorithm: (1) fetch active-status, (2) purge DB SKUs that are inactive, (3) compute candidate SKUs (active but not in DB), (4) call quantity API only for candidates and import only those with quantity > 0.
  • New imports are enriched by fetching product data (get_product_data) for fields like moin, weight, my_price, sale_price, and category so created records are immediately useful.
  • Result: drastically fewer API calls, deterministic purge behavior, and more complete article records on import.

🐛 Bug Fixes

  • Fixed toggle persistence: clearing cached article pages after toggling "Use Min/Max Rules" so the UI shows the persisted value immediately instead of stale cached data.

  • Prevented spurious recalculation on Kaufland article updates: the endpoint now only triggers recalculation when fields were explicitly sent and actually changed (uses model_fields_set), so manually-saved maximum_price and other fields are not overwritten.

  • Fixed CRUD update behavior that prevented clearing fields to null: removed an overly-strict value is not None guard so null values from the client are now persisted.

  • Frontend: after saving an article the cache is now cleared and a forced refetch is performed so the UI shows saved values immediately (avoids stale localStorage entries).

  • Fixed a bug in the Plenty population cron workflow where a FastAPI Query(...) default leaked into a direct function call and was passed to SQLAlchemy as a value (error: "can't adapt type 'Query'").

  • Root cause: endpoint-style parameter defaults (e.g. snapshot_date: Optional[date] = Query(None)) are FastAPI wrappers and are not automatically unwrapped when the function is invoked directly from Python code.

  • Fix: explicitly pass snapshot_date=None when calling calculate_and_update_stock_values from the populate workflow, ensuring SQLAlchemy receives None rather than a Query object. This prevents SQL binding errors during the FIFO stock-value calculation and allows the cron job to complete.

SQL