Table of Contents

Changelog

Version 28.0.0.3 (2026-09-14)

New Features

  • Cross-selling translations maintainable via the custom API: New sub-entity shopItemCrossSellingTranslations (key shopwareXSellId + languageCode, field name) below shopItemCrossSellings, analogous to shopItemTranslations. Widget names can now be created, changed and deleted for every shop language directly from BC; translations are sent to Shopware with the next cross-selling sync. Prerequisite: the language has a Shopware ID (see Setup).

  • Order completion optionally only with tracking number: New setting "Complete Only With Tracking" in the Shopware setup. When enabled, the order-complete transition is only sent to Shopware once all posted shipments of the order have a tracking number (e.g. for dropshipping). If the tracking number is entered after invoicing, the completion is sent then. The completion also waits until a pending tracking transmission has been sent. Shipping agents without tracking numbers (e.g. letter mail) can be exempted with the new field "No Tracking Required" on the shipping agent.

  • Variant axes are now registered automatically: When syncing parent products with variants, the selectable variant axes (e.g. "Size", "Color") are now automatically sent to Shopware. Shopware does not derive this on its own from the variants - without this registration, the storefront showed no variant selector on the product page even though every variant was created correctly.

Bug Fixes

  • PRODUCT_CONFIGURATION_OPTION_EXISTS_ALREADY during variant axis reconciliation: The lookup of existing variant axes (configuratorSettings) could not read Shopware's response in JSON:API format, found no existing entries and tried to create them again. Both response formats are now understood.
  • Duplicate property groups on creation: Creating a property group with a name that already exists now raises an error instead of silently creating a duplicate in Shopware.
  • Guest orders overwrote master data of registered customers: When a registered customer ordered as a guest using the same e-mail address, the order was assigned to the existing customer and its name, address and e-mail were overwritten with the guest data. Guest orders now always create their own separate customer; they are no longer matched to existing customers by Shopware ID or e-mail.

Version 28.0.0.2 (2026-09-04)

Bug Fixes

  • Newly created property options were never pushed to Shopware: Property options created locally in BC (e.g. via the Property Options ListPart or the variant options picker) stayed local-only until someone manually ran the "Sync to Shopware" action on the property group card. If such an option had already been assigned to an item and the item was fully synced, the sync failed with a foreign key error on the Shopware side because the option didn't exist there yet. New options are now automatically pushed to Shopware individually right when they're created; if the push fails, the local creation of the option is rolled back and the error is shown instead of leaving an orphaned option in BC.
  • Failed manual property group sync went unnoticed: The "Sync to Shopware" action on the property group card showed neither an error nor the success message when the sync failed - the failure was silently swallowed. Retrying looked like success even though nothing was synced. Failures are now shown with the full Shopware response text.

Version 28.0.0.1 (2026-08-27)

New Features

  • More master data tables show a readable title: Card pages and drilldowns for custom fields, custom field options and translations, property groups/options, voucher codes/discounts, rules, delivery times, feature sets, and other master data tables now show the name or code as the title instead of the internal Shopware GUID (matching Category, Custom Field Set, Channel, Voucher, Shop Item, and Order).

Bug Fixes

  • Property Options – property group empty on new lines: New lines in the Property Options ListPart did not automatically pick up the property group provided by the calling context. Now pre-filled correctly on creation.
  • Promoting a variant to a root product was not synced to Shopware: Clearing a shop item's parent product id (turning a variant into its own root product) left the old assignment untouched in Shopware, because the sync never sent the cleared value. If the item is missing name, category/channel/media/custom-field assignments or translations that its old parent had, this is now reported in the transaction protocol instead of being silently dropped (can be deliberately overridden via the new "Force Promotion Sync" action on the product card); purely technical fields (tax class, manufacturer, unit, delivery time, etc.) and the price are copied down from the old parent automatically.
  • LockTable error on token expiry during batch runs: If the Shopware token expired while an HTTP batch (price, stock, product sync, etc.) was running, the internal re-login caused a runtime error because it triggered a table lock inside a TryFunction. Re-authentication now runs without a table lock via the existing in-memory refresh.
  • Wrong transaction protocol tag for the direct full sync: The "Send directly to Shopware" action always sends the complete product payload, but logged its entries under the incremental sync tag. Now correctly logged as "Product Full Resync".
  • VAT registration no. and VAT business posting group during order import: The VAT ID is now read from the customer level instead of the address-level field Shopware stopped populating back in version 6.4 — affected both the VAT registration no. on the sales header and the automatic B2B customer template assignment. The VAT/gen. business posting group is now set on every order based on the actual ship-to country, not only once when the customer is first created — so an existing customer ordering to a different country still gets the correct posting group.

Version 28.0.0.0 (2026-06-25)

New Features

  • Multi-select Categories: The "Add Categories" action on the product card now lets you check multiple categories at once in a selection list and assign them all with a single click on "Add Selected". Already assigned categories are skipped automatically.
  • Language-Specific Custom Field Values: New page "Shopware Custom Field Value Translations" for managing Custom Field values per language. Accessible via the "Translations" action in the Custom Field Values ListPart. The subpage now shows only language-independent entries (Language Code = empty) by default.
  • SEO Main Category per Channel: On the Channels tab of the product card, an SEO main category can be set for each sales channel. It is transferred during product sync and import from Shopware (Shopware mainCategory entity). The category picker now automatically filters by the navigation category of the respective channel.
  • Item No. on Channel Assignment: The new "Item No." field on the Shop Item Channel assignment allows entering a BC item number. The Shopware Product ID is resolved automatically — useful for Rapidstart imports.
  • Create Property Group Manually: New "New Group" action in the property group picker to create groups without importing from Shopware.
  • Editable Option Name: The option name in the property option picker is now directly editable.
  • Custom Search Keywords: New field "Custom Search Keywords" on the SEO tab of the product card. Enter multiple keywords separated by semicolons. During sync they are sent as an array (customSearchKeywords) to Shopware; during import from Shopware they are read back.
  • Search Keywords per Language (Ticket #320): The "Custom Search Keywords" field is now also available per Shopware language in product translations (previously single-language only on the main item). Sent to Shopware per language automatically during sync and read back on translation import.
  • Parent/Child Channel Cascading: When a child product (variant) is assigned to a sales channel, that channel assignment is automatically propagated to the parent product if the parent does not yet have an assignment for that channel. When a channel assignment on the parent is deactivated, the corresponding channel assignments of all child products are also deactivated.
  • Array Support in Payload Variables: JSON paths in the order line payload configuration can now point to arrays. For each array element, a separate variable row is stored for every scalar field — with key format [0].fieldname, [1].fieldname etc. This enables extraction of e.g. payload.properties arrays from Shopware plugins.
  • OData REST API for Shop Items: New API page msgreentec/shopware/v1.0/shopItems — external systems can trigger sync actions (stock, prices, full sync, etc.) via HTTP and import products by Shopware UUID. See Public API.
  • Product Media Overview List: New "Shopware Product Media" page shows all locally recorded image metadata across products — set as cover, delete, or import from Shopware directly from the list.
  • Sync Buffer – "Process Now" for All Sync Types: The action previously processed only Category entries, regardless of what was selected in the list. It now covers all sync types and processes only the currently selected rows.
  • List Price (Streichpreis): New "List Price" field on Sales Price and Price List Line, editable via the standard BC "Sales Prices"/"Price List Lines" pages. Sent to Shopware during price sync as a listPrice object on the base price and on each quantity tier, controlling the crossed-out reference price in Shopware.
  • Price and List Price Editable Directly on the Product Card: The Sales Prices subpage now automatically shows the source matching the active pricing feature (legacy "Sales Price" or the new price list feature) instead of always the legacy table. Only price and list price are editable; all other fields as well as adding/deleting rows remain locked.
  • Exclude Cancelled/Failed Orders on Fetch: New channel field "Exclude Cancelled/Failed Orders" — excludes orders that can never be converted (cancelled or failed payment) already when fetching from Shopware, instead of first creating them as a never-convertible Shopware Order in BC. Orders with an open/unconfirmed payment status are unaffected. Disabled by default.
  • 52 New IntegrationEvents: All batch sync functions (price, inventory, visibility, category, category-order, and delivery-state sync) now get the same before/after hooks as their already-hooked single-record counterparts. Also added new events at previously unhooked spots in order import, customer creation, sales line building, product/price JSON building, and item management. See Events & Extensibility.
  • Bulk API Access Hardened: To comply with Shopware hosting providers' requirements for bulk API access, the extension now waits a configurable pause after every request, honors Retry-After on HTTP 429 (otherwise exponential backoff, max. 5 attempts), and automatically refreshes the OAuth token in the background on HTTP 401. Price, inventory, product, visibility, category, and cross-selling changes are also no longer sent individually but bundled via the Shopware Sync API. See Installation & Setup.
  • Create Order Without Automatic Release: New "Release Order" field on the "Shopware Accepted Payment States" list — lets you control, per combination of payment method and payment state, whether the BC order created during import is released automatically or stays in "Open" status for manual review. Enabled by default (previous behavior). See Order Import.
  • Create/update product images via API: The OData API's shopItemMediaList sub-entity now supports Insert and Modify instead of read-only access. Either register an image already uploaded to Shopware (set the metadata directly) or let BC perform the full upload (send the image as a base64 string in the new base64Content field). Changes to the cover image and position are now actively reported to Shopware, not just stored locally. See Public API.
  • Product Card Shows/Edits Translations in User Language: Name, description, and SEO fields (incl. pack unit) on the Shop Item card are now read from and written to the translation record matching the BC session language, falling back to the new Shopware default language from Setup. When the session language matches the default language, changes are also mirrored into the product's base fields (and vice versa) — so there's no more duplicate maintenance of the default language. The default language is now detected automatically during language sync, based on Shopware's fixed system language ID.
  • Transaction Log Counters on Product Card and List: New fields show the number of processed and failed transaction log entries per product, with click-through drill-down into the filtered log. Errors are highlighted in color on the product list.
  • "Send to Shopware (Queue)": New action on the product card, product list (with multi-select), and OData API queues a product for a full sync (Sync Buffer/Job Queue) instead of sending it immediately and blocking. Useful for many products at once, since the Job Queue already has rate-limit protection and bulk-batching built in. The existing direct action is now labeled "Send directly to Shopware" for a clearer distinction.
  • Permission Concept Split into Role and Feature Sets: Instead of a single full-access permission set, 4 composed role sets (Administrator, Catalog Manager, Order Processor, Job Queue User) and 13 atomic feature sets are now available. The previous full-access set remains unchanged as a fallback under "BC2Shopware - Super"; existing assignments are automatically re-linked on update. See Installation & Setup.
  • New Shopware Address Fields: Additional address line 1/2, salutation, title, department, and VAT ID are now imported from Shopware order addresses in addition to the existing address fields. When transferring to the sales document and creating/updating the customer, street and additional address lines are distributed component by component across the "Address"/"Address 2" fields, and the billing address VAT ID is copied into "VAT Registration No.". See Order Import.
  • Manual Cancellation on the Shopware Order Card: New "Cancel Order in Shopware" action on the Shopware Order List and Card triggers the cancellation independent of the "Send Cancel to Shopware" switch, without changing the BC sales order. See Order Lifecycle Sync.
  • Shipping Date on Delivery State Sync: When transmitting the tracking number to Shopware, today's date is now also sent as shippingDateEarliest/shippingDateLatest (+3 days) on the Shopware delivery. Previously, the estimate Shopware calculated at checkout remained even after the actual shipment. See Order Import.
  • "Refresh from Shopware (Queue)": New action on the product card and product list (with multi-select) queues a product for a background refresh from Shopware (Sync Buffer/Job Queue) instead of fetching all data immediately and blocking. Useful for many products at once, since a single refresh triggers up to 9 separate Shopware requests. See Item Synchronization.
  • Open in Shopware Backend: New action on the Shopware order list/card and shop item list/card opens the respective record directly in the Shopware Administration in a new browser tab. The URL templates ("Shopware Admin Order URL Template"/"...Product URL Template") are freely configurable in Setup, since backend deep links can differ depending on the shop/custom overview.
  • Progress Bar for Previously Silent Bulk Actions: Around 23 page actions with multi-select or loop processing (including refresh from Shopware, price/inventory sync, voucher and category sync, and various fetch/process imports) now show a progress bar instead of a frozen UI. "Create Order" additionally gets a success/failure counter with a completion message.
  • New "Shopware Manager" Role Center: Dedicated role center with its own profile for the Shopware integration — KPI cues for orders with errors, pending category syncs, sync buffer backlog, and transaction log errors, plus quick links to master data, sales, and monitoring. Optionally available as a hidden cue also on the "Business Manager" role center (requires personalization by the respective user). See Shopware Manager Role Center.
  • 2 New IntegrationEvents for HTTP Retry Diagnostics: OnHttpRetryAttempt (on every 429/502/503/504 retry) and OnAfterSendHttpRequestWithRetry (after every HTTP call, including total duration and retry counts) let a separate extension log rate limiting and transient server errors without modifying BC2Shopware itself. See Events & Extensibility.
  • Suppress Automatic Sync via API (DisableAutoSync / EnableAutoSync): New bound actions on the OData API's shopItems entity let external systems suppress every automatic sync trigger for a product (changes via the API itself, custom field values, translations, cross-selling, price self-heal) while pushing a batch of changes, and re-enable it once the batch is complete. Manual sync actions (SyncToShopware, SyncStock, ...) keep working while disabled. A new read-only autoSyncDisabled field shows the current state. See Public API.

Bug Fixes

  • Custom Field Sync: The product number is now correctly written to CF value records when importing custom field values.
  • Custom Field Import: The entity type is now correctly read from the page filter (instead of the record field value, which defaulted to category on empty subpages).
  • Category Picker: Now expanded by default; path filter removed.
  • SEO Main Category Picker: Implemented as a dedicated action to work around the FlowField-Editable limitation.
  • Category Multi-Picker: Now uses direct database writes instead of state return via RunModal, preventing assignment errors in certain BC versions.
  • NavJsonToken→NavJsonValue: Conversion error in payload variable extraction fixed.
  • Guest Orders: Orders without a Shopware customer ID (guest orders) were blocked by a customer filter and never converted to BC sales orders. Now processed correctly.
  • Item Sync – POST instead of PATCH for new products: ProcessShopItemSyncEntries incorrectly sent a PATCH instead of a POST for new products. New products are now correctly created via POST.
  • Price Sync – Reactivation on Price Creation: When a new price is entered for an item that was never successfully created in Shopware before (e.g. because the initial POST failed for lack of a price), a full product sync (POST) is now queued automatically instead of an ineffective price-only PATCH.
  • Cross-Selling Sync: Failed permanently when the associated product did not yet exist in Shopware (foreign key violation). The transfer is now deferred and automatically retried once the product exists.
  • ProcessTranslationDeleteSyncEntries: Fixed HTTP 404 for translations that were already unsynced.
  • Properties Assignment on Product Card (Ticket #317): Reworked for clarity — guided assignment via property group selection and option picker, plus automatic group/option filtering for direct row entry.
  • Custom Field Value Import: Now correctly branches by entity type; import implemented for categories; language-specific translations are fetched during import.
  • Custom Field Value Translations: The Custom Field's name is now shown as a heading instead of its own column.
  • Product-Category Sync: Switched to the Prepare/Process pattern with transaction log (analogous to category sync) — failed assignments no longer disappear silently but are logged with an error message.
  • Locale Code Comparison: Language comparison during import is now case-insensitive (DE-DE and de-DE are both recognized).
  • Field Lengths: Field lengths for category and property labels adjusted to match the actual Shopware API limits.
  • Product Creation without Price/Channel: The base product (master data, categories, custom fields, translations, images) is now always sent to Shopware, even without an assigned sales channel or a configured price (falls back to 0.00 in the company currency). Previously the product stayed invisible in Shopware until pricing was fully configured.
  • Image Upload on Unsynced Products: Now shows a clear message ("product not yet synced") instead of a raw database error when uploading an image for a product that was never successfully created in Shopware.
  • Category, Visibility, Inventory, and Active Sync on Non-Existent Products: These four sync operations sent PATCH requests to products that were never successfully created in Shopware and failed with a cryptic framework error. A full product create (including categories/visibilities/stock/active flag) is now queued automatically instead of letting the request fail.
  • Field Lengths for Name/Meta/Pack Unit/Keywords: Adjusted to match the actual Shopware field limits (verified against source code): Name, Meta Title, Meta Description, Pack Unit and Pack Unit Plural extended to 255 characters (previously as low as 50-100), Keywords extended to the BC maximum of 2048 characters (Shopware itself has no limit here). Applies to both the main product and translations.
  • Property Assignment on Child Products: Adding new rows in the Properties ListPart on variants (child products) failed with "The key field type Text cannot be automatically split". Caused by an incorrectly set AutoSplitKey, which cannot work for the table's text-based key — now removed.
  • Sync Buffer – Channel ID Column: Hidden by default, since the field is always set to 0 when buffer entries are created and is never evaluated anywhere in the code.
  • Variant Options Assignment on Product Card: Reworked analogous to the Properties assignment (Ticket #317) — guided selection via property group and option picker with multi-select in a single session, automatic group/option filtering for direct row entry, and automatic sync triggering when the display order (configurator groups) changes.
  • Variant Options/Properties – Deletion Failed: Removing a variant option or property assignment sent a DELETE to an invalid Shopware route ("api/product-option/…" resp. "api/product-property/…", HTTP 405) and was incorrectly recorded as successful instead of being logged as an error. The correct route is the association route on the product itself ("api/product//options/" resp. ".../properties/"); errors are now visible in the transaction log.
  • Product List "Sync to Shopware": Despite the identical caption to the product card action, this sent only base data (no prices/categories/properties/options) for existing products. Switched to the same full sync as the product card; the now-redundant "Full Sync to Shopware" action was removed.
  • Prices for Inactive Channels: Prices were previously only calculated for active channel assignments. When a channel was activated (in BC or directly in Shopware), customers could briefly see a never-sent 0.00 price. Prices are now kept up to date for all assigned channels regardless of active status; visibility, categories, and base data remain tied to the active status as before.
  • Price Sync Status Flag and Multi-Currency Volume Pricing: The Is Price Synced field was previously set for all price lines of an item, regardless of whether their Customer Price Group/Price List was even assigned to a synced channel. Also, when a Customer Price Group/Price List had prices in multiple currencies, only the currency of the lowest quantity tier was used — other currencies were sent with the wrong currency ID. Both are now correctly grouped by channel assignment and currency.
  • Accepted Payment States per Payment Method – List Not Editable: The Shopware Accepted Payment States list could not be filled in due to an incorrectly set property — new rows could be inserted but no values entered. Now editable again.
  • Channel Tables Consolidated: The separate Sales Channel table has been merged into Shopware Channel. Both tables were effectively always maintained 1:1; of the Sales Channel's fields, only the Order Comment Code was actually used and has been moved to the Shopware Channel. Unused fields (customer no., customer template, standard/B2B flags, send order confirmation, dropshipping) were removed, as they were never evaluated anywhere in the app.
  • Voucher Discount on Wrong Line: A Shopware voucher's header invoice discount was silently reset to 0 by a later rounding correction whenever an order line was modified afterwards — the discount was lost or ended up applied uncontrolled to the first item line instead. The voucher amount is now applied directly to the line Shopware designates as the target (discountedItemId).
  • Address Import Aborts on Long Fields: If a Shopware address field (e.g. street) exceeded 50 characters, the entire GetAddresses job queue run aborted with an uncaught error instead of skipping only the affected order. All address fields are now correctly truncated to their field length.
  • Shopware Order List – Column Order: Order number is now the first column, BC order number the second; the Shopware ID is hidden by default (still available via the column selector).
  • Unified German Label for "Process Get Orders": The German transaction log caption is now "Aufträge verarbeiten" (was "Bestellungen verarbeiten"), consistent with the other order-related German labels. No change to the English caption.
  • Payment Method Not Clickable in Shopware Order List: Clicking the Payment Method field previously did nothing. It now drills down to the Payment Methods list, filtered to the matching payment method.
  • Single-Image Preview on the Product Media List: The Shopware Product Media list now shows a FactBox with the currently selected image as a preview (instead of none, or the full product gallery).
  • Removed Deprecated Sales Channel Objects: The Sales Channel MGT table (deprecated a while ago) and its card/list pages (replaced by Shopware Channel) have now been fully removed from the extension.
  • OData API Bound Actions Were Unreachable: The actions documented on shopItems (SyncToShopware, SyncStock, ImportMedia, etc.) were implemented as regular page actions with an OnAction trigger — on an API page with no UI surface, these never executed. Now implemented as proper bound actions with [ServiceEnabled], callable via POST .../shopItems('<id>')/Microsoft.NAV.<Action>.
  • Properties/Variant Options/Configurator Groups Missing After Automatic Sync: Adding a property, variant option, or configurator group previously only triggered the lightweight active-status sync, which never transmits this data — only a full product sync (e.g. via "Sync to Shopware") includes it. As a result, newly added properties were missing in the shop until a manual sync was run. A new "Product Full Resync" sync type now automatically triggers the full product sync instead.
  • Name Inheritance on Variants: Assigning a parent product to a product now automatically clears its own Name field. During sync, a blank name is sent as an explicit null instead of an empty string, so the variant correctly inherits the name from its parent product.
  • Orphaned Custom Field Values: If a Custom Field value was created before its Custom Field Set was imported locally (e.g. via the public API), "CF Set Id" and "CF Id" stayed permanently blank. Both fields are now derived automatically from the Custom Field name on creation; if the name cannot be resolved, creation now fails with a clear error instead of allowing an incomplete record.
  • Job Queue Entries Silently Froze: Root cause found for a days-long "job queues get stuck" issue: "No. of Minutes between Runs" only takes effect when at least one weekday (Monday…Sunday) and a time window (starting/ending time) are also set. Without these, an entry ran once and then froze with no visible error instead of being rescheduled. All job queue entries created by the extension (including the watchdog) now automatically set all 7 weekdays plus a 00:00:00–23:59:59 time window.
  • Translation Fields Hidden by Default: Meta title, meta description, keywords, custom search keywords, and pack units were hidden in product translations even though they can be maintained there. Now visible by default.
  • Multi-select Categories Didn't Work: The category picker collected checked rows in a buffer variable and only applied them via a separate confirm button — when checking multiple categories, only the last one checked was actually assigned. The checkbox now writes directly to the assignment table immediately, matching the variant option picker.
  • Custom Field Sync – Text Values in Integer/Number Fields: Translation values (with a language code set) previously skipped field-type validation — allowing free text into e.g. an Integer custom field, which Shopware then rejected for the entire product request with "This value should be of type int." Validation now applies to translation values too; an Integer/Number value that can't be evaluated is now skipped during sync instead of being sent as text.
  • Product Sync Failed on Blank Property Option Id: The properties/options array didn't skip rows with a blank option ID, causing Shopware to reject the entire request with FRAMEWORK__INVALID_UUID. Also, the existing self-heal for products deleted directly in Shopware (FRAMEWORK__WRITE_TYPE_INTEND_ERROR) was only wired into visibility sync — the actual product sync now resets the sync status and immediately retries a full create as well.
  • Job Queue Product Sync Didn't Self-Heal: Same failure mode as above, but in the actual job queue path (not the interactive sync action) — a product deleted directly in Shopware failed with the same error on every automatic run instead of automatically re-creating itself, as already worked for the visibility batch sync.
  • Order Number and Customer Name in Order Card Header Had No Effect: DataCaptionFields is ignored by the page when PageType=Document — the property must be set on the underlying table instead (a known AL quirk). Moved from the page to the "Shopware Order MGT" table.
  • Product Number Drifted After Renaming: Renaming a Shop Item's product number was previously only propagated to dependent tables (translations, custom field values, product media, cross-selling) at creation time, not on a later rename. A new trigger now mirrors changes into all affected tables. Additionally, the Cross-Selling import left the product number blank on every import (insert without running triggers) — now set explicitly.
  • Field Inheritance Blocked by Empty BC Values: When a BC field was blank, its JSON key was previously omitted entirely from the sync payload instead of being sent as an explicit null. Shopware leaves an omitted key unchanged on PATCH, permanently blocking variant inheritance once a variant ever had its own value. Besides the long description, this affected EAN, manufacturer number, tax rate, manufacturer, unit, delivery time, CMS page, feature set, all dimensions, purchase settings, reference price fields, release date, SEO fields, and custom search keywords (which were sent as an empty array instead of null). Number/date fields now also treat 0 or a blank date as "not set" and send null.
  • FastTab Caption "Shopware" Missing: The Shopware group on the Customer Card and Item Category Card had no Caption property and displayed the technical object name "ShopwareMGT" instead of "Shopware".
  • Reading/Writing the Description via the OData API: The product description could not be read or written via the "Shopware Shop Item API MGT" and "Shopware SI Trans. API MGT" API pages. Since Blob fields don't work reliably as a plain JSON field (writes were silently lost both on creation and on any later change to an already-set value), there are now dedicated bound actions GetDescriptionText/SetDescriptionText plus a read-only hasDescription field. See Public API.
  • Product Number Missing on Property Assignments: The "Product Number" field on "Shopware Shop Item Prop. MGT" was a FlowField and didn't work reliably via the OData API. Like the existing Product Number fields on custom field values and translations, it's now a stored field that gets filled on creation and kept in sync automatically when the product is renamed.
  • Product Translations – Description No Longer Editable in the Row: The description is internally a Blob field and could be displayed in the translation row, but not reliably edited across multiple lines. The field is now read-only in the row; clicking it opens a dedicated editor with proper multi-line input. All other translation fields remain directly editable in the row as before.
  • Product Number Missing on Shop Item Category Assignments: The "Product Number" field on the Shop Item Category assignment was a FlowField and didn't work reliably via the OData API. Like the existing Product Number fields, it's now a stored field that gets filled on creation and kept in sync automatically when the product is renamed.
  • Removing a Category Always Failed: Removing a category from a product sent DELETE to "api/product-category/{productId}/{categoryId}" — this Shopware API route only allows GET/POST, not DELETE (405 Method Not Allowed). It now sends the full remaining category list via PATCH instead, same as when assigning. Also fixed a blank option/property ID producing an incomplete URL when deleting a variant option or property assignment, which failed the same way.
  • Custom Field Sync – Language-Specific Values Missing: Custom field values with a language code set were not sent to Shopware during product sync, only the language-independent ones. They are now embedded into the matching translation per language as well.
  • Long Description Truncated on Read: Multi-line descriptions (products, translations, categories) were only read up to the first line break, both during sync to Shopware and when displaying/editing in BC. Stored data was unaffected, only reading — the full content is now read correctly.
  • Transaction Log Actions Reworked: The "Shopware Trans. Prot. Entr MGT" page now offers all 53 functions actually created via the job queue (including the watchdog) as actions, grouped by category. Removed outdated migration/test functions and plain wizard setup functions that don't create their own job queue entry.
  • Property/Variant Option Assignment – "Value Not Found": Selecting an option via the property picker, or "Add Option" in the variant options ListPart, failed because the option validation ran before the record's property group was set. Order fixed.
  • Default-Language Mirroring Also via API/Import: Changes to the default-language translation were previously only mirrored into the Shop Item's base fields when edited via the card/ListPart. Now also applies when writing via the public API and when importing from Shopware; a blank translation skeleton with no content no longer triggers the mirroring.
  • List Price No Longer Omitted at 0: A list price set to (or cleared to) 0 was not sent during sync, leaving a previously set compare-at price visible in Shopware. Now sent explicitly as null, like other inherited fields.
  • Creating a New Variant Failed on Required Fields: Name and VAT product posting group were required even for variants, even though these are intentionally left blank to inherit from the parent product. Both checks are now skipped when a parent product is assigned.
  • Customer Matching by E-Mail: Matching an order to an existing customer by e-mail now only succeeds when the e-mail address uniquely identifies exactly one customer. On a unique match, the Shopware customer ID is now also backfilled onto the customer so future orders match via the more robust ID lookup.
  • Product Number Rename Did Not Cascade Fully: Renaming a shop item's product number during automatic Shopware reconciliation was not reliably propagated to all related tables (only 2 of 7). Switching to Validate() now triggers the full, already existing cascade.
  • Blocking Table Lock During Cross-Selling Reimport: Repeated import of cross-selling assignments from Shopware locked the entire shop item table for its full runtime (SQL UPDLOCK caused by a database cursor kept open across multiple commits), blocking parallel operations such as item push, inventory/price sync, or order import. Affected IDs are now collected upfront, so the cursor is already closed while processing.
  • Orphaned Return Sync Buffer Entries When Cancellation Feature Disabled: If sending returns/received returns to Shopware was disabled after a sync buffer entry had already been created, that entry stayed unprocessed in the sync buffer indefinitely. An upgrade step cleans up existing orphaned entries once, if the feature is currently disabled.
  • Product Media Overview List Now Partially Editable: The "Shopware Product Media" page was completely read-only. Position and "Is Cover" can now be edited directly in the list; all other fields remain read-only.
  • Error Flag Stayed Set Permanently After a Status Change: A Shopware order that could not be processed into a BC order (e.g. because its payment state was not yet accepted) stayed permanently excluded from further processing attempts once the Error flag was set — even if the payment state later successfully changed to "paid". The Error flag is now automatically cleared whenever the order, payment, or delivery state changes during the periodic payment status refresh.
  • Second Shopware Delivery for Split Shipments Could Fail Silently: If an order was shipped in multiple independent partial shipments (e.g. dropshipping and main warehouse handled separately), creating the second, independent Shopware delivery could fail on a transient error (e.g. rate limiting, gateway error) without producing any error message or log entry anywhere — the associated tracking number then never reached Shopware. Failed attempts are now visible in the transaction log. The shipping address ID needed for this is also now cached at order import time, so creating the second delivery no longer requires an extra live call to Shopware in the common case.
  • Logged Delivery Creation Error Showed Identical Request/Response Text: A failed attempt to create a Shopware delivery previously wrote the same text into both the "Request" and "Response" fields of the transaction log. The actual POST body sent and Shopware's real response are now logged separately.
  • Invoice PDF Sync Got Permanently Stuck After a Shopware Storage Error: If creating the invoice document at Shopware failed after the document number had already been reserved (e.g. due to a transient storage error), Shopware rejected every subsequent retry with DOCUMENT__NUMBER_ALREADY_EXISTS — surfaced as a misleading message ("could not parse documentId...") instead of the real cause, so the sync got stuck again on every retry. A document number collision is now detected and the document already existing at Shopware is reused for the PDF upload instead of attempting to recreate it under the same number.
  • Property/Variant Option Assignment Still Blocked via the OData API: The earlier fix to the validation order (see "Property/Variant Option Assignment – 'Value Not Found'" above) only fixed the two UI flows (property picker, "Add Option"). Writes via the OData API (shopItemProperties/shopItemOptions, see Public API) still checked "Option Id" against the record's own "Property Group Id" field, which was still blank at that point — rejecting every API-assigned option that actually existed with "not found". The existence check now happens directly in the Option Id's OnValidate trigger instead of via the automatic TableRelation validation.
  • Media Refresh Fetched Every Image Individually: The "Update from Shopware" action issued a separate Shopware request per image assignment just to read its URL/file name. For products with many images (e.g. variants with their own image), this noticeably slowed down the refresh. The image data is now fetched inline as part of the already-required image assignment call; the individual fetch remains only as a fallback for the rare case where an assignment doesn't come back embedded.
  • Rule Creation Failed with Uppercase UUID: The rule ID was generated without LowerCase(); Shopware's ID fields only accept [0-9a-f]{32} (FRAMEWORK__WRITE_CONSTRAINT_VIOLATION), the same issue already fixed for the second Shopware delivery.
  • Price Sync Queue – Duplicate Entries for Items with a Pending Log Entry: QueueProductPriceSyncEntry previously only checked the Sync Buffer for duplicates. An item whose price sync had already been handed off to the transaction log but not yet processed could be queued a second time. Now also checks whether an unprocessed, non-error PriceSync entry already exists in the transaction log.

Version 27.0.0.0

Initial release of MSGreenTec® BC2Shopware.

Return Sync

  • New codeunit Shopware Return Sync MGT (71987654) synchronizes BC sales return orders to Shopware in two steps
  • Release → Returned: Releasing a sales return order automatically sets the Shopware delivery status to Returned (POST /api/_action/order_delivery/{id}/state/retour)
  • Post → Refund: Posting the sales return order automatically submits the resulting credit memo as a refund to Shopware
  • New setup flag Send Return to Shopware
  • New job queue entries: PrepareReturnReceivedSyncEntries / ProcessReturnReceivedSyncEntries
  • The Shopware Order ID is automatically resolved from the original invoice via the Applies-to Doc. No. field if not directly set on the return order

Order Import – Status Filtering & Error Handling

  • Pre-filter invalid statuses: Orders with cancelled order state, failed or cancelled payment state, or cancelled delivery state are skipped when creating sales orders
  • Soft error behaviour: Instead of throwing an exception, invalid orders are flagged with an error message in the status field and skipped (no abort of the entire run)
  • Commit per order: Each sales order is committed individually after creation to avoid long transactions during large imports

Order Lifecycle Sync

  • New codeunit Shopware Order Lifecycle MGT (replaces Shopware Cancel Sync MGT) consolidates all order-related status transitions
  • Order completion: When a BC sales order is fully invoiced, the Shopware order status is automatically set to "Completed" (state/process + state/complete)
  • New setup flag Send Complete to Shopware
  • Manual action Mark as Complete in Shopware on the order list and order card
  • New job queue entries: PrepareOrderCompleteSyncEntries / ProcessOrderCompleteSyncEntries
  • Cancellation functionality remains unchanged

Custom Fields on Order Lines

  • During order import from Shopware, customFields on order line items are automatically read and stored
  • New entity type Order Line Item (order_line_item) in the custom field configuration
  • New FactBox Order Line Custom Fields on the Shopware Order Card
  • Action Custom Fields directly on order lines

Order Line Payload Variables

  • New feature for configurable extraction of payload variables from Shopware order lines
  • New Shopware Order Line Payload Config table (Search → Order Line Payload Config): define JSON paths whose values are extracted during order import
  • Extracted key-value pairs are stored per order line in the Shopware OrdLn Pld Var MGT table
  • New FactBox Order Line Payload Variables on the Shopware Order Card shows the variables for the currently selected order line
  • Action Payload Variables directly on order lines for a line-specific detail view
  • Support for scalar paths: if a path points to a scalar value (instead of an object), it is stored with the last path segment as the key (e.g. path personalizationText → variable personalizationText)
  • New action Reload Payload Variables on the Shopware Order Card: re-fetches payload data from Shopware (useful after configuration changes)
  • Table is public and can be read from customer extensions

Sales Prices Sub-Page on the Shop Item Card

  • New Sales Prices tab on the Shopware Shop Item Card shows BC sales prices for the linked item
  • Default view shows only currently valid prices; toggle action to include expired entries

Order Import – Enhancements

  • Status fields as enums: Order State, Payment State and Delivery State are type-safe enums mapped directly from Shopware API names — filterable in the order list
  • Refresh Open Order Status: New action and Job Queue entry that queries the current Shopware status of all open orders
  • Shipping Agent n:1 Shopware IDs: New table allows mapping multiple Shopware shipping method IDs to one BC shipping agent
  • Shipping cost line as Resource: Shipping costs can alternatively be posted as a BC Resource instead of an item on the sales order
  • Tracking number in delivery state sync: Package tracking number and Shopware shipping method ID are automatically included in the delivery state sync; three overloads of QueueDeliveryStateSyncForShipment for explicit control

Item Sync – Enhancements

  • Fetch from Shopware by ID: New action in the Shop Item List fetches a single Shopware product by UUID — even if it does not yet exist in BC. Creates or fully updates the record (master data, categories, properties, custom fields, channels, media, translations, cross-selling).
  • Action bar grouped: Actions in the Shop Item List are now organized into four groups: Manage, Send to Shopware, Load from Shopware, Scheduled.
  • Import Products Since Date: New action imports Shopware products filtered by creation/modification date
  • Automatic sync on BC item data change: Changes to BC item master data (description, EAN etc.) automatically queue the linked Shop Item for sync
  • Standalone list pages: Translations, category assignments and property assignments are now available as separate, searchable pages via Tell Me
  • Shopware Indexing Control: Indexing is automatically disabled during large sync runs and re-enabled via the Shopware queue afterwards (significantly faster mass transfers)

Price Sync – Enhancements

  • Multiple currencies: Prices in different currencies are sent to Shopware as separate objects in the price array
  • Price Sync Status: New Is Price Synced field on Sales Price lines and Price List Lines shows the timestamp of the last successful transfer

Channel Management

  • Active flag on Shopware Channel: Inactive channels are automatically excluded from all sync operations

Extensibility

  • New events: OnBeforeInsertSalesLine / OnAfterInsertSalesLine in codeunit Shopware Sales Document for customizing individual sales lines during order import

Bug Fixes

  • Order import: CreateSalesOrders cursor bug — Passing the iterating record by reference to CreateSalesDocument, which internally called SetRecFilter(), corrupted the FindSet cursor and caused only the first order to be processed per job queue run. A separate record variable is now used for each iteration.
  • Order import: Error filter in CreateSalesOrders — Orders flagged with Error = true are now skipped by CreateSalesOrders to prevent repeated failed attempts on already-known problematic orders.
  • Order lifecycle: ProcessOrderCompleteSyncEntries error handling — The state/complete transition was called unconditionally even when state/process failed (HTTP 40x). The call is now correctly guarded: state/complete is only sent when state/process succeeds; errors are recorded in the transaction log.
  • Payment refresh: authorized payments re-queued unnecessarily — Orders with payment state authorized were incorrectly excluded from the exit condition in QueuePaymentRefreshIfNeeded, causing unnecessary payment refresh requests. authorized is now treated as a final state.
  • Delivery state sync: duplicate sync for same shipment — If a shipment had already been sent to Shopware (Shopware Sent = true), it was queued again on subsequent runs. The check now exits early when the flag is set.
  • Delivery state sync: tracking code not persisted — Tracking codes were not written to the ShipDelivery record before the sync. They are now stored in Tracking Codes so that re-queuing on tracking number change works correctly.
  • Variant selector sync: configuratorGroupConfig was incorrectly sent as a standalone top-level field in the PATCH body. Shopware 6.7 expects this array nested inside variantListingConfig. The bug caused Shopware to ignore the configuration, leaving configuratorGroupConfig permanently null.
  • Price sync: duplicate price entries prevented — Shopware was creating new entries on each price sync instead of updating existing ones because the prices array did not include id fields. Deterministic IDs are now computed (from product ID, rule ID, and quantity tier) and orphaned entries are automatically deleted before the PATCH.
  • Channel-specific prices for single-tier entries — Prices were only sent when more than one price tier was present (TierCount > 1). Entries with exactly one tier are now correctly transmitted as channel-specific prices.
  • quantityStart sent as Integer — Shopware rejected the payload with HTTP 400 because quantityStart was sent as a decimal (1.0) instead of an integer (1).
  • Order import: duplicate key error in GetOrderLines — Importing order lines caused a "record already exists" error because the table's primary key (Shopware order ID, position, line ID) was not passed in full. All three key fields are now checked correctly.
  • Order import: JSON null safety in all parsing functions — In BC18, AsValue().AsText() throws a runtime error when the JSON value is null. All parsing functions (order lines, addresses, payments) are now null-safe.
  • Delivery state sync: shipping method ID resolution — The Shopware shipping method ID is now reliably resolved via the shipping agent mapping table. Falls back to the stored order shipping method if no mapping is found.
  • RefreshOpenOrderStatus: endless loop for cancelled orders — Already cancelled or refunded Shopware orders were re-checked indefinitely. They are now skipped.

Improvements

  • Import from Shopware action on all Shop Item Card subpages: Channels, Categories, Properties, Configurator Groups, Custom Fields, and Translations each now have an Import from Shopware action that fetches the respective data for the current product directly from Shopware — without a full re-import.
  • Configurator Groups import with fallback: If variantListingConfig.configuratorGroupConfig is null in Shopware (explicit configuration was not saved), the involved property groups are automatically derived via the configuratorSettings endpoint and stored with default values. A subsequent sync writes the configuration correctly to Shopware.
  • Cross-selling second pass on full import: After all products are imported, a second cross-selling import run is performed for each product. This ensures that product-list type widgets are correctly imported even when their assigned products were created in BC later in the same import run.
  • Variant options for child products — New Variant Options tab on the Shop Item Card (visible on child products only). Allows assigning specific property options per variant (e.g. "Size: L", "Color: Red"). The options array is included in the product sync payload so that the Variant column in the Shopware admin is correctly populated. Import from Shopware via optionIds is also supported.
  • Shipping agent Shopware IDs (n:1): A BC shipping agent can now be mapped to multiple Shopware shipping method IDs (e.g. for different sales channels). New Shopware Shipping Agent IDs table as a standalone list page with direct editing.
  • Shipping cost as Resource: The shipping cost line item on order import can optionally be configured as a BC Resource instead of an Item.
  • Status fields as Enums: Order, payment, and delivery status are now stored as type-safe enums instead of free text, enabling reliable filtering and evaluation.
  • RefreshOpenOrderStatus: New job queue entry that periodically refreshes the status of open Shopware orders from Shopware and updates the stored status fields in BC.
  • BC Order No. lookup: Clicking the BC order number in the Shopware order list now opens the corresponding Sales Order card directly.
  • Cross-selling: automatic sync via Prepare-Process pattern — New and modified cross-selling entries are automatically queued (on insert/modify in BC) and asynchronously transferred to Shopware via the PrepareXSellSyncEntries and ProcessXSellSyncEntries job queues.
  • Cross-selling: Product Number field — New "Product Number" field on the cross-selling table and the translation table. Populated automatically on insert; existing records are backfilled via an upgrade function. The product number is shown as the first field on the cross-selling card.
  • Product Streams: import action — New Import from Shopware action directly on the Product Streams list.

Order Import

  • Automatically import Shopware orders as sales orders in Business Central
  • Line items, addresses, and payment information are transferred
  • Customer assignment and automatic customer creation
  • Configurable order release and email notification
  • Automatically send delivery state back to Shopware: when a shipment is posted in BC, the Shopware delivery state is set to shipped (Shopware State Machine Transition API)
  • Manual action "Send Delivery State to Shopware" on order card and list

Item Sync

  • Create and sync BC items as Shopware products
  • Complete field mapping (master data, dimensions, SEO, order settings, unit pricing)
  • Variant support (multiple BC items per Shopware product)
  • Translations for product names, descriptions, and SEO fields
  • Match function: link existing Shopware products by item number
  • Variant listing: variantListingConfig (display parent, main variant) and configuratorGroupConfig (selector type per property group: Box, Select, Image, Color) are included in the sync; new Configurator Groups tab on the Shop Item Card
  • BC item description in product list: Computed FlowField shows the BC item description directly in the product list
  • Cross-Selling: Bidirectional synchronization of cross-selling widgets (product list and product stream); import, sync, and delete; translations and assigned products fully supported

Categories

  • Category import from Shopware with full hierarchy
  • Category sync with two-stage buffer pattern
  • Sorting via linked list (afterCategoryId) – atomic sync API
  • Display types: Page/List, Structure Element, Link
  • Product assignment type: Manual Selection and Dynamic Product Groups

Price Sync

  • Automatic price synchronization on changes to sales prices or price lists
  • Volume pricing with configurable Shopware rule ID (select from imported rules via lookup)
  • Dynamic VAT calculation (gross/net) via VAT business posting group
  • Support for legacy sales prices and new price lists
  • Import Shopware rules: "Import Rules from Shopware" action on the channel card loads all rules for lookup selection
  • Rules in Setup Wizard: Shopware rules are now imported in Step 4 (Reference Data) – dedicated "Fetch Rules" button and included in "Fetch All"; rules are available before channel configuration
  • Planned prices: New daily job queue entry QueueDailyPriceSync (1440 min.) automatically queues items whose sales price or price list line starts today and sends them to Shopware
  • Item deactivation on missing price: When the last valid price for an item is deleted, BC automatically sets the item to active=false in Shopware (ProcessShopItemActiveSyncEntries)

Inventory

  • Automatic inventory synchronization on item ledger entry changes
  • Stock calculation across all linked BC items of a product
  • Manual synchronization via product card and product list
  • Closeout item support

Multi-Channel

  • Multiple Shopware sales channels simultaneously
  • Separate prices, categories, and visibilities per channel
  • Configurable customer price groups and dimension assignment
  • B2B and drop shipping configuration

Shopware Reference Master Data (Dropdown Fields)

  • Fields for manufacturer, unit of measure, delivery time, CMS page, and feature set on the Shop Item Card are dropdown lookups instead of manually entered UUIDs
  • New field "Shopware ID MGT" on BC manufacturer and BC unit of measure records for the UUID mapping
  • The Shopware UUID is automatically resolved from the linked record during sync
  • Shopware Delivery Time MGT – Delivery times from Shopware (Id, Name, Unit, Min, Max)
  • Shopware CMS Page MGT – CMS pages from Shopware (Id, Name, Type)
  • Shopware Feature Set MGT + Shopware Feature MGT – Feature sets and their features from Shopware

Shopware Properties (Filter Attributes)

  • New tables Shopware Property Group MGT (71987609) and Shopware Property Option MGT (71987610) for property groups and their options from Shopware
  • New Properties tab on the Shop Item Card: n:m assignment of property options to products
  • During sync, assigned options are sent as a properties array (UUIDs) in the product JSON
  • Import via Fetch Property Groups (Setup Wizard Step 4 or "Shopware Property Groups MGT" page)
  • Property translations (N languages): translations for group and option names are loaded during import and synced via the Shopware Sync API
  • Option images: each property option can be assigned an image (drag & drop in FactBox, direct upload via Shopware Media API)
  • Sync via PATCH /api/property-group-option/{id} with mediaId; removal via PATCH with null + DELETE /api/media/{id}

Custom Fields

  • Import and sync of custom field set definitions
  • Supported entity types: Product, Category, Manufacturer, Customer, Customer Address, Order, Delivery Time
  • 11 field types (Text, Integer, Number, Select, Checkbox, DateTime, and more)
  • Manage custom field values directly in BC and sync to Shopware
  • Select/MultiSelect options are imported with labels (German/English) and stored in a dedicated table
  • MultiSelect values are correctly serialized as JSON arrays when sent to Shopware and deserialized when received
  • Toggle lookup for MultiSelect: add or remove options with a single click
  • DateTime fields are sent to Shopware as ISO 8601 format
  • Translations (N languages): Custom Field Sets, Fields, and Options can be translated into any number of languages; translations are loaded during import and fully included in sync; changes to translations automatically reset the sync status of the set

Vouchers (Shopware Promotions)

  • Bidirectional synchronization of Shopware promotions with BC
  • Import: POST /api/search/promotion with associations discounts and promotionIndividualCodes via job queue/transaction log
  • Processing: voucher, discount, and individual code records are automatically created and updated
  • Sync to Shopware: POST (new) or PATCH (existing) to /api/promotion/{id}
  • Management UI: Voucher List, Voucher Card with discount and code sub-pages
  • New job queue parameters: GetPromotionsImport, ProcessPromotionsImport

Public API

  • Activate/deactivate products via AL code: SetShopItemActive, SetShopItemActiveByBCItemNo
  • Master deactivation with automatic parent lookup: SetShopItemMasterActive, SetShopItemMasterActiveByBCItemNo
  • Buffered sync via job queue (PrepareShopItemActiveSyncEntries, ProcessShopItemActiveSyncEntries)
  • Deactivating a parent product automatically hides all variants in Shopware
  • New procedure CreateShopItemVariantFromMaster(MasterItemNo, VariantItemNo, Width, Height, Sort, Active) in codeunit ShopwareAPI Shop Item Mgmt MGT (71987583)
  • New codeunit Shopware Refund Sync MGT (71987591) with procedure SendRefundToShopware(ExternalDocumentNo, RefundAmount, CrMemoNo) for refunds
  • New codeunit Shopware Cancel Sync MGT (71987592): cancellation on order deletion via QueueOrderCancelToShopware(), controlled by a switch in Shopware Setup
  • New codeunit Shopware Invoice PDF Sync MGT (71987593): automatically upload the invoice as PDF to Shopware after posting
  • New codeunit Shopware Media Upload MGT (71987594): upload product images via drag & drop or API to Shopware, incl. UploadImageForBCItem(), UploadImageStreamForBCItem(), DeleteAllImagesForBCItem()

Product Images

  • Drag & drop image upload directly from the Shop Item Card to Shopware
  • Images are not stored in BC — they are sent directly to the Shopware Media API
  • FactBox with image gallery shows product images from Shopware URLs
  • Set cover image, reorder and delete images directly from the gallery
  • Import existing images from Shopware via the "Import Media from Shopware" action
  • Supported formats: JPG, PNG, GIF, WebP, SVG (max 10 MB)

Events & Extensibility

  • 49 IntegrationEvents for all sync processes
  • OnBefore/OnAfter pattern with IsHandled support
  • JSON payload customization via OnAfterBuild events

Setup & Operations

  • Setup wizard (10 steps) for guided initial configuration
  • Automatic job queue creation on installation
  • Configurable maximum batch size per job queue run
  • Transaction log with configurable retention period
  • MSGreenTec licensing app integration
  • Reset All Shopware Data: New action on the setup page to completely delete all imported Shopware data and clear Shopware IDs on BC master data (for shop migration)
  • Connection test with error details: The connection test in the wizard now shows specific error messages (e.g. missing configuration, network errors, HTTP error code with Shopware response)
  • Shopware 6.7 compatibility: Accept header corrected (application/json instead of application/json; charset=utf-8)