Abgleich: vorhandene ERPNext Artikel mit Shopware Artikeln verknüpfen #15

Closed
opened 2026-05-10 16:44:17 +00:00 by csaeum · 1 comment
csaeum commented 2026-05-10 16:44:17 +00:00 (Migrated from gitlab.localdomain)

Vorhandene ERPNext Items nachträglich mit Shopware-Produkten verknüpfen:

  • Abgleich über Artikelnummer (Item Code = Shopware Product Number)
  • Bei Übereinstimmung: Shopware Product ID in Custom Field eintragen
  • Bereits verknüpfte Artikel überspringen
  • Bericht über verknüpfte und nicht gefundene Artikel ausgeben
  • Als einmalig ausführbarer Frappe Script oder Button im UI
Vorhandene ERPNext Items nachträglich mit Shopware-Produkten verknüpfen: - Abgleich über Artikelnummer (Item Code = Shopware Product Number) - Bei Übereinstimmung: Shopware Product ID in Custom Field eintragen - Bereits verknüpfte Artikel überspringen - Bericht über verknüpfte und nicht gefundene Artikel ausgeben - Als einmalig ausführbarer Frappe Script oder Button im UI
Owner

Implemented in a new ecommerce_integrations/shopware6/api/reconcile.py (reconcile_items()), plus a whitelisted Shopware Account.reconcile_items() method and a new "Reconcile Items" button.

Research (Julian/Marcel): the underlying "match by SKU, link, don't touch anything else" pattern predates both forks — it's copied near-verbatim in both from this repo's own existing Shopify (shopify/product.py:273) and Unicommerce (unicommerce/product.py:124) connectors, not a Shopware-specific contribution. Julian's _match_sku_and_link_item() (shopware6/product.py:393) is a silent fallback baked into product import (no report, one DB query per Shopware product, no UI button, links via a new Ecommerce Item row). Marcel's product_sync/api.py:509 auto_adopt_by_sku() is much closer to this issue — its own whitelisted endpoint with a UI button and an {adopted, skipped_already_mapped, no_match, ambiguous} report, batched via Shopware's equalsAny filter to avoid N+1 lookups.

Design decisions:

  • No need to reproduce Marcel's API-side batching: our own list_products() (from #13, reused unchanged) already fetches the whole catalog in one paginated sweep (live-tested at 2279 products in #13/#14), so an in-memory productNumber → (shopware_id, is_variant) lookup dict avoids N+1 on both sides without any extra machinery.
  • Links via the existing shopware_product_id/shopware_variant_id Custom Fields (from #13/#14), not Ecommerce Item — consistent with the prior two issues and the issue's explicit requirement.
  • Only the ID field is set on a match; no other Item field is touched, and a match against a variant SKU does not retroactively restructure the Item into an ERPNext variant (out of scope).

Live verification: two pre-existing test Items (one matching a real parent SKU, one matching a real variant SKU) were correctly linked via the respective field, with all other fields left untouched; a third Item with a non-existent SKU stayed unlinked. Second run reported both as already_linked and relinked nothing (full idempotency). Test data cleaned up after verification.

See Projekt.md → Architecture Decisions for the full writeup.

Milestone 4 is now complete — all 4 issues (#12-#15) closed.

Implemented in a new `ecommerce_integrations/shopware6/api/reconcile.py` (`reconcile_items()`), plus a whitelisted `Shopware Account.reconcile_items()` method and a new "Reconcile Items" button. **Research (Julian/Marcel):** the underlying "match by SKU, link, don't touch anything else" pattern predates both forks — it's copied near-verbatim in both from this repo's own existing Shopify (`shopify/product.py:273`) and Unicommerce (`unicommerce/product.py:124`) connectors, not a Shopware-specific contribution. Julian's `_match_sku_and_link_item()` (`shopware6/product.py:393`) is a silent fallback baked into product import (no report, one DB query per Shopware product, no UI button, links via a new `Ecommerce Item` row). Marcel's `product_sync/api.py:509` `auto_adopt_by_sku()` is much closer to this issue — its own whitelisted endpoint with a UI button and an `{adopted, skipped_already_mapped, no_match, ambiguous}` report, batched via Shopware's `equalsAny` filter to avoid N+1 lookups. **Design decisions:** - No need to reproduce Marcel's API-side batching: our own `list_products()` (from #13, reused unchanged) already fetches the whole catalog in one paginated sweep (live-tested at 2279 products in #13/#14), so an in-memory `productNumber → (shopware_id, is_variant)` lookup dict avoids N+1 on both sides without any extra machinery. - Links via the existing `shopware_product_id`/`shopware_variant_id` Custom Fields (from #13/#14), not `Ecommerce Item` — consistent with the prior two issues and the issue's explicit requirement. - Only the ID field is set on a match; no other Item field is touched, and a match against a variant SKU does not retroactively restructure the Item into an ERPNext variant (out of scope). **Live verification:** two pre-existing test Items (one matching a real parent SKU, one matching a real variant SKU) were correctly linked via the respective field, with all other fields left untouched; a third Item with a non-existent SKU stayed unlinked. Second run reported both as `already_linked` and relinked nothing (full idempotency). Test data cleaned up after verification. See `Projekt.md` → Architecture Decisions for the full writeup. **Milestone 4 is now complete** — all 4 issues (#12-#15) closed.
Sign in to join this conversation.
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Frappe-Projekte/ecommerce_integrations#15
No description provided.