Skip to content

Bulk APLT → Medusa Import


The bulk import script (bulk_medusa_import.js) reads from magic_pim.aplt_products and inserts directly into the target Medusa database (magic_b2b_*). It populates all 9 tables that make up a complete Medusa product:

aplt_products (source)
product ← main product record
product_option ← "Kleur" option (one per product)
product_option_value ← one per unique color
product_variant ← one per variant (with SKU)
product_variant_option ← links variant ↔ option value
price_set ← one per variant
price ← tiered price amounts (100/200/300/500/1000 qty)
product_variant_price_set ← links variant ↔ price_set
image ← product images (optional)

Everything runs inside one transaction per supplier — if anything fails, the entire supplier batch rolls back cleanly.


Each supplier uses a different SKU structure. The script groups APLT rows into Medusa products using supplier-specific logic:

SupplierBase SKU (product)Variant SKUExample
Spranz (01)Before first dotvariant_code101-05 / 101-05.001
Langenberg (03)sku as-isvariant_code10015 / 10015-01
XD Connect (04)sku as-isvariant_codeP308 / P308.399
PF Concept (05)sku as-isvariant_codeK0404 / K04041RM
MidOcean (06)sku as-isvariant_codeAR1804 / AR1804-03
Toppoint (07)sku as-isvariant_codeLT87694 / LT87694-N2102
NewWave (09)sku as-isvariant_code027310 / 027310-55-5

The script lives at /tmp/bulk_medusa_import.js and runs inside the backend container where the pg module is available.

Terminal window
# Copy into container (if not already there)
docker cp /tmp/bulk_medusa_import.js magic_pim_backend_dev:/app/.medusa/server/
# Dry run — shows counts without touching data
docker exec magic_pim_backend_dev sh -c \
"cd /app/.medusa/server && node bulk_medusa_import.js 06 --dry-run"
# Run for a single supplier
docker exec magic_pim_backend_dev sh -c \
"cd /app/.medusa/server && node bulk_medusa_import.js 06"
# Run for all suppliers
docker exec magic_pim_backend_dev sh -c \
"cd /app/.medusa/server && node bulk_medusa_import.js all"
CodeSupplier
01Spranz
03Langenberg
04XD Connect
05PF Concept
06MidOcean
07Toppoint
09NewWave
allAll of the above

Terminal window
# Backup
docker exec magic_pim_postgres_dev pg_dump -U postgres magic_b2b_development \
| gzip > /mnt/data/backups/magic_b2b_development_$(date +%Y%m%d_%H%M%S).sql.gz
# Restore if needed
gunzip -c /mnt/data/backups/magic_b2b_development_YYYYMMDD_HHMMSS.sql.gz \
| docker exec -i magic_pim_postgres_dev psql -U postgres magic_b2b_development

Executed before the actual import. Existing records are detected by handle and skipped automatically.

SupplierAPLT RowsProductsNew ProductsVariantsPricesAlready in Medusa
Spranz (01)7604913852250454
Langenberg (03)2442440244 ✅
XD Connect (04)11,5269401163,6046,2682,610
PF Concept (05)19,4312,4982,49819,43119,4310
MidOcean (06)14,4962,4432,44314,49614,4960
Toppoint (07)5,8561,8421,8425,8566,4260
NewWave (09)26,23995995926,23993,7230
Total78,5529,4177,89669,678140,594

Run after dry run. The script skips handles that already exist in Medusa globally (all suppliers) and post-verifies variant inserts to handle unique constraint conflicts on barcode/EAN.

SupplierProducts InsertedVariants InsertedPrices InsertedSkipped (conflicts)
Spranz (01)3852250
Langenberg (03)0All already in Medusa
XD Connect (04)1141,7862,038577 variants (barcode/EAN conflict)
PF Concept (05)2,4916,36019,40519,405Fixed: barcode nulled for supplier 05 — all variants now inserted
MidOcean (06)2,44314,49214,4924 variants (barcode conflict)
Toppoint (07)1,8425,8566,426
NewWave (09)95926,23993,723
Total new5,88767,830136,334

Medusa dev totals after import + PF Concept fix: 11,195 products · 72,336 variants · 146,728 prices


The following are handled separately or not yet implemented:

  • Category linksproduct_category_product records are not inserted. Run a separate category sync after the bulk import.
  • Medusa product sync hash — Products inserted this way won’t have a sync_hash in metadata. The next run of medusa-sync will re-sync and update them via the API path.
  • Tenant databases — This script targets one database at a time. To import into Brinxx or other tenants, change DEV_CONFIG.database in the script.
  • Update existing — The script only inserts new products (skipped by handle). To update existing ones, delete them first or use medusa-sync for updates.

”⚠ N variants skipped (unique constraint conflicts)” Normal — the script post-verifies which variants were actually inserted and automatically filters product_variant_option, price_set, price, and product_variant_price_set to only reference inserted variants. No action needed unless the count seems unexpectedly high.

Transaction rolled back Check the error message. Most FK constraint issues were fixed in the 2026-03-12 revision. Common remaining causes: schema mismatch (wrong Medusa version), or a column type error in the insert values.

“relation does not exist” You’re targeting the wrong database. Verify the DEV_CONFIG.database value matches the container’s actual DB name.