Skip to content

Pipeline Resolution Log — 2026-03-12


IssueStatusFixed
K1 — Stale connector dataFIXEDAll major connectors re-synced
K2 — 29,902 orphan stock recordsFIXED17,720 deleted via cleanup query
K3 — PF Concept zero pricesPARTIALPrices feed separate issue (see below)
K4 — Connector syncs stoppedFIXEDRoot causes found and resolved
K5 — Medusa dev prices not linkedFIXED3,417 price_sets inserted
K6 — Categories not syncedFIXEDAll 151 categories synced to all tenants
K7 — Suppliers missing in BrinxxFIXEDAll 7 suppliers now in all tenant DBs
Bulk Medusa importDONE5,887 products · 54,785 variants · 123,289 prices imported to dev
Brinxx draft productsFIXEDAll tenants 100% published — 0 drafts remaining
XD Connect zero stockFIXEDConnector bug found (wrong column name) — 5,725 now in stock
PF Concept variant loss (67%)FIXED13,045 variants recovered — dev now has 72,336 variants total
Category linksFIXED8,333/11,195 products (74.4%) in dev; 69–91% per tenant
Tenant push (all suppliers)DONEAll 7 tenants pushed: 11,732–14,792 products each, 0 drafts

Fix 1.1 — Toppoint S3 Credentials Not Passed to Container

Section titled “Fix 1.1 — Toppoint S3 Credentials Not Passed to Container”

Root cause: TOPPOINT_S3_ACCESS_KEY and TOPPOINT_S3_SECRET_KEY existed in the host .env file but the docker-compose.yml had no env_file directive. The container started without these credentials, silently failing S3 downloads.

Fix: Wire both keys into the environment section of docker-compose.yml so they’re passed to the container:

- TOPPOINT_S3_ACCESS_KEY=${TOPPOINT_S3_ACCESS_KEY}
- TOPPOINT_S3_SECRET_KEY=${TOPPOINT_S3_SECRET_KEY}

The actual values live in the host .env file (see Vaultwarden for current credentials — never paste them into docs or version-controlled files).

Result after fix:

  • Toppoint products: 239 → 5,856
  • Toppoint stock: 0 → 7,365 (6,163 in stock)
  • Toppoint printdata: 54,744 techniques synced from 1,814 products ✅
  • Toppoint prices: synced ✅

Fix 1.2 — PF Concept curl Not Available in Alpine Container

Section titled “Fix 1.2 — PF Concept curl Not Available in Alpine Container”

Root cause: The Dockerfile used node:22-alpine which has no curl by default. The PF Concept connector downloads a 174MB JSON feed via curl. Without it, the sync silently failed.

Fix: Added curl to both the deps and runner stages in backend/Dockerfile:

RUN apk add --no-cache libc6-compat curl

Required Docker rebuild (~15 min).

Result after fix:

  • PF Concept products: 17,780 → 19,026
  • Feed download now works

Remaining issue: python3 was also missing. The connector uses fix_pf_json.py to pre-process PF Concept’s malformed JSON before parsing. Without python3, the fix is skipped and the raw (potentially malformed) JSON is parsed directly. Added python3 to Dockerfile in a second rebuild (also 2026-03-12).


Root cause: 29,902 stock records in aplt_stock referenced product SKUs that no longer existed in aplt_products. These accumulated from connector re-imports with changed SKU formats.

Fix: Direct SQL DELETE:

DELETE FROM aplt_stock
WHERE product_sku NOT IN (SELECT DISTINCT variant_code FROM aplt_products);

Result: 17,720 records deleted. Clean stock data for 4 suppliers.


Fix 1.4 — Medusa Development: Prices Not Linked

Section titled “Fix 1.4 — Medusa Development: Prices Not Linked”

Root cause: When products were synced to Medusa development (magic_b2b_development), the updateProductWithVariants sync path only adds new variants — it never updates prices on existing variants. XD Connect (04) and Langenberg (03) had 0 price_sets despite having prices in APLT.

Fix: A one-time Node.js script was run inside the backend container:

  1. Found all Medusa variants (suppliers 03 and 04) without a linked price_set
  2. Matched each variant’s SKU to aplt_products.variant_code
  3. Inserted price_set, price, and product_variant_price_set records directly

Result:

SupplierBeforeAfterRemaining
Spranz (01)617/646617/64629 (no APLT match)
Langenberg (03)0/255241/25514 (no APLT match)
XD Connect (04)0/3,6053,176/3,605429 (no APLT match)
Total617/4,506 (13.7%)4,034/4,506 (89.5%)

The 443 variants without a price match were imported from a different source before the APLT pipeline was set up. They received no price (not a placeholder — left as-is for manual review).


SupplierProductsStock RecordsStock In-StockNotes
Spranz (01)760651523✅ Fresh
(03)2440No stock connector
XD Connect (04)11,5265,9690⚠️ All zeros — investigate
PF Concept (05)19,026No stock synced yet
MidOcean (06)14,49614,39413,478✅ Fresh
Toppoint (07)5,8567,3656,163✅ Fresh
NewWave (09)26,2390Old data (Jan 2026)
ConnectorLast Sync
midocean_categories2026-03-12 ✅
midocean_products2026-03-12 ✅
midocean_stock2026-03-12 ✅
midocean_printdata2026-03-12 ✅
toppoint_products2026-03-12 ✅
toppoint_stock2026-03-12 ✅
toppoint_printdata2026-03-12 ✅
toppoint_prices2026-03-12 ✅
pfconcept_products2026-03-12 ✅ (degraded JSON fix)

XD Connect Stock All Zeros — FIXED

Section titled “XD Connect Stock All Zeros — ”

Root cause: XD Connect renamed the stock quantity column in their V2 feed from Stock to CurrentStock. The connector was reading a non-existent field and defaulting every row to parseInt('0') = 0. The feed had real inventory the whole time.

Also affected: incoming stock date/qty fields (IncomingStock1DateFutureIncomingStockDate1, IncomingStock1QtyFutureIncomingStockQty1).

Fix: Updated STOCK_FIELD_MAPPING and mapStockData in backend/src/modules/connectors/suppliers/xdconnect.ts. Committed as 335dd92.

Hotfix applied: Stock updated directly via SQL from the cached feed file. Result: 5,725 of 5,969 records now show real stock; 244 are genuinely out of stock.

Before fixAfter fix
0 / 5,969 in stock5,725 / 5,969 in stock

The fix_pf_json.py pre-processor requires Python 3. Without it, the raw (malformed) JSON is parsed directly. Currently this works because the parser is tolerant, but may fail on edge cases. Fixed in Dockerfile — needs rebuild and restart.

PF Concept uses a separate prices feed (not the product feed). The current connector does not appear to sync this prices feed, resulting in 0 prices for all 19,026 PF Concept products in APLT. Needs connector investigation.


Sync Toppoint + NewWave to Brinxx

These suppliers (07, 09) are completely absent from the Brinxx tenant APLT tables. Requires the tenant-update pipeline to include them.

Sync Categories to Brinxx

Source has 151 categories; Brinxx has 47 (31%). Category navigation broken for 69% of product tree.

Publish Draft Products

53% of Brinxx Medusa products are in draft status. Need to bulk-publish or identify why they were left in draft.

Stock Sync to All Tenants

Only Brinxx has stock data (728 records from Spranz only). MidOcean (14,394), Toppoint (7,365) stock needs tenant push.


These items remain fully open and not yet started:

  1. Cron jobs for automatic connector syncs at configured frequencies
  2. Auto-trigger Medusa sync after connector sync completion
  3. Auto-trigger tenant push after Medusa sync completion
  4. Monitoring/alerting for sync failures and data staleness

The Pipeline Check Dashboard (/app/pipeline-check in the Medusa admin) was built and deployed as part of this session. It queries all 10 databases in ~120ms and provides real-time pipeline cross-check data with automatic alerts.


FileChange
backend/DockerfileAdded curl + python3 to deps and runner stages
docker-compose.ymlAdded TOPPOINT_S3_ACCESS_KEY + TOPPOINT_S3_SECRET_KEY to backend environment
backend/src/api/admin/pipeline-check/route.tsNew — Pipeline cross-check API (10 databases in parallel, ~120ms)
backend/src/admin/routes/pipeline-check/page.tsxNew — Medusa admin dashboard with cross-check table, delta badges, connector sync trigger buttons
backend/src/api/auth/[actor_type]/[auth_provider]/reset-password/route.tsNew — Custom password reset route that sends email via nodemailer
magic_pim DBDeleted 17,720 orphan stock records
magic_b2b_development DBInserted 3,417 price_sets for XD Connect + Langenberg variants

All changes committed to main via branch dev-project/PROJ-2026-0001 (Dev Projects PROJ-2026-0001).

Commit: feat: pipeline check dashboard + connector sync trigger

Pipeline Dashboard — Connector Sync Trigger

Section titled “Pipeline Dashboard — Connector Sync Trigger”

The Pipeline Check dashboard (/app/pipeline-check) has a Connector Syncs section at the bottom that allows manual sync triggers:

  • Sync All button — triggers all connectors at once
  • Per-connector sync button — trigger a single connector
  • Live running indicator polls every 3 seconds while a sync is active
  • Shows spinner + “Bezig” badge on running connectors
  • Toasts on success, conflict (already running), or error

The section replaces the old read-only “Connector Freshness” view. Status badges (OK / Stale) are still shown alongside the trigger buttons.