Skip to content

1.8.14

⚙️ Patch 1.8.14 — Plenty retours import & parent order linking

🚀 Summary

  • Plenty retours storage — return orders (orderTypeId=4) are fetched from Plenty, stored in a new plenty_retours table (one row per returned article line), and linked to the original sales order via parent_order_id.
  • has_retour on plenty_orders — parent sales orders are flagged when a retour exists; missing parent orders are backfilled from Plenty automatically during retour import.
  • Profit cron & UI — daily profit cron now imports yesterday's retours; Statistics → Profit tab has a manual retour date-range import panel.

✨ Improvements

Database

Table / column Purpose
plenty_retours Flat retour lines: retour_id, parent_order_id, item/SKU, amounts, retour_date, origin, shipping destination
plenty_orders.has_retour BOOLEAN, indexed — true when at least one retour references this sales order_id

Migration: docker/postgres/updates/add_plenty_retours_and_has_retour.sql
Fresh installs: docker/postgres/tables/plenty_retours.sql + updated plenty_orders.sql.

service-omni — Plenty API

Route Purpose
POST /api/v1/omni/plenty/retours?date=YYYY-MM-DD Fetch & store retours for one day
POST /api/v1/omni/plenty/retours/range?start_date=…&end_date=… Backfill retours for a date range

Plenty search filter: orderTypeId in [4] + orderDate_2 between start/end of day (same timezone pattern as orders).

Parent resolution: orderItemSummary.parentOrderId → fallback orderReferences (referenceType: "parent") → fallback reverseOrderReferences.

Backfill flow: After storing retours, any parent_order_id not yet in plenty_orders is fetched via GET /rest/orders?orderIds=…, upserted, and marked has_retour=true.

Response fields (PlentyRetoursResponse):

Field Meaning
total_lines Retour article lines stored
parent_orders_total Unique parent sales order IDs referenced
parent_orders_fetched Parent orders newly imported from Plenty
parent_orders_marked Unique parent orders with has_retour=true
parent_orders_missing Parent IDs Plenty did not return

Profit cron (Statistics)

The existing plenty_orders_runner cron now runs, in order:

  1. Retry unpaid pending orders
  2. Fetch yesterday's Plenty sales orders
  3. Fetch yesterday's Plenty retours (+ parent backfill)
  4. Sync yesterday's Amazon FBA orders

Cron endpoints unchanged: POST /statistics/profit/cron/start|stop, GET /statistics/profit/cron/status.

Frontend

Area Change
Statistics → Profit New card Manual Plenty Retour Date Range Import
API client profitStatisticsApi.storeRetoursForDateRange(start, end)
Success message Shows retour lines, backfilled parents, marked count, and any missing parents

DB sync

plenty_retours added to scripts/db-sync/tables.json (full + profit presets).

🔧 Deploy

  1. Run migration on Postgres:
    psql -f docker/postgres/updates/add_plenty_retours_and_has_retour.sql
    
  2. Rebuild / restart service-omni.
  3. Rebuild frontend (Profit tab retour import UI).
  4. Rebuild docs if you publish patchnotes from the repo.
  5. Optional: backfill historical retours via UI or API before relying on has_retour in Metabase.

✅ Verify

  1. Single day:
    POST /api/v1/omni/plenty/retours?date=2026-07-13200, total_lines > 0, parent_orders_marked matches unique parents.
  2. Parent backfill: Import retours for a day where parent sales orders were never imported → parent_orders_fetched > 0, corresponding rows appear in plenty_orders with has_retour=true.
  3. Metabase: SELECT order_id, has_retour FROM plenty_orders WHERE has_retour = true returns expected IDs; join plenty_retours.parent_order_id = plenty_orders.order_id.
  4. Cron: After next profit cron run, logs show retour fetch step without error.
  5. UI: Statistics → Profit → Import Retours for a date range → success toast with fetched/marked counts.
  6. Tests: pytest backend/service_omni/app/tests/test_plenty_retours.py

⚠️ Notes

  • Retours are filtered by retour creation date (orderDate_2), not the original sales order date — parent orders may be from weeks earlier; backfill handles that.
  • has_retour is set on all line rows sharing the same order_id in plenty_orders.
  • Re-importing retours for the same retour_id replaces existing rows (upsert by retour id).
  • Plenty property typeId=4 on orders is payment status (fullyPaid); return orders use top-level typeId: 4 (order type) — do not confuse the two when debugging.

Files touched

service-omni

  • app/services/plenty/plenty_manager.pysearch_retours, _parse_retour_entries, fetch_orders_by_ids
  • app/crud/plenty_retours.py — retour upsert + parent marking
  • app/crud/plenty_orders.pyhas_retour, get_existing_order_ids, mark_has_retour
  • app/api/v1/endpoints/plenty.py/retours, /retours/range, _store_retours_for_date
  • app/api/v1/endpoints/statistics.py — cron retour step
  • app/models/plenty.py, app/schemas/plenty.pyPlentyRetourLine, PlentyRetoursResponse, PlentyRetourLineRecord
  • app/tests/test_plenty_retours.py

frontend

  • src/pages/Statistics/Tabs/ProfitTab.jsx — retour import card
  • src/services/api/omni/statistics.jsstoreRetoursForDateRange

database / sync

  • docker/postgres/tables/plenty_retours.sql
  • docker/postgres/tables/plenty_orders.sqlhas_retour column
  • docker/postgres/updates/add_plenty_retours_and_has_retour.sql
  • scripts/db-sync/tables.json

docs

  • docs/docs/patchnotes/1.8/1.8.14.md — this file
  • docs/docs/services/service_omni/endpoints/plenty.md
  • docs/docs/services/service_omni/endpoints/statistics.md
  • docs/docs/services/service_omni/services/plenty_orders_retours.md
  • docs/docs/services/service_omni/services/plenty.md