Skip to content

Conversation

@tamvt
Copy link
Contributor

@tamvt tamvt commented Jan 12, 2026

In this PR:

  • We need to migrate product states <-> product type and product type <-> product type
  • Product type PR: https://github.com/shopware/shopware/pull/13554/files
  • We need to exclude products with type grouped_bundle when migrating because the product bundles are not yet compatible with MIG yet.

@tamvt tamvt self-assigned this Jan 12, 2026
@tamvt tamvt linked an issue Jan 12, 2026 that may be closed by this pull request
@tamvt tamvt changed the title feat: Compatible with migration assistant feat: Compatible with product bundle Jan 12, 2026
@tamvt tamvt marked this pull request as draft January 12, 2026 10:39
@tamvt tamvt force-pushed the 13167-compatible-with-migration-assistant branch from fe24be0 to 54eaaea Compare January 16, 2026 04:19
@tamvt tamvt force-pushed the 13167-compatible-with-migration-assistant branch from 54eaaea to fc9865c Compare January 16, 2026 08:22
@tamvt tamvt marked this pull request as ready for review January 16, 2026 08:42
@larskemper larskemper requested review from a team, DennisGarding, MalteJanz, ennasus4sun, jozsefdamokos, larskemper and vintagesucks and removed request for a team January 16, 2026 15:00
Copy link
Contributor

@MalteJanz MalteJanz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for reaching out and taking care of this change 👍 . But I think we need to discuss a little further about the chosen approach and figure out a more robust one 🙂

Comment on lines +77 to +85
// Check if product already exists (was previously migrated) before creating mapping
// This is needed because the 'type' field has Immutable flag and can only be set on create
$existingMapping = $this->mappingService->getMapping(
$this->connectionId,
DefaultEntities::PRODUCT,
$data['id'],
$this->context
);
$isUpdate = $existingMapping !== null;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At first look, this is a clever attempt to determine if this entity will run into an insert or update. But unfortunately it contains a flaw 🙈 .

Yes on the first migration run this will tell you if the product "was previously attempted to migrate" and thus give the the wanted result.

But if the migration for this entity somehow fails:

  • either further down in this converter
  • in the validation layer that comes after - which we currently implement in our feature branch
  • or later while writing the entity to the corresponding SW6 table

it would mean the next migration run (retry) would still consider this entity as an "update", because the mapping already exists, which produces the wrong outcome in this case.

We have to think further about this, to not introduce yet another N+1 Query performance issue 😬

$converted = $data;

// Check if custom field set already exists (was previously migrated) before creating mapping
// This is needed because the 'name' field has Immutable flag and can only be set on create
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for not raising this concern earlier:

Do you really think it's a good idea to have such a ImmutableFlag ? (Was introduced in this PR )

Because I already see the extra work it creates for us here, every entity that uses that flag needs an extra special treatment in the migration and if someone adds that flag to other fields in the future (or introduces such fields), we will run into issues again.

It basically makes "upserts" (insert / update) really difficult to do for such entities, because you want to create them if they don't exists yet, or update them otherwise, so you need the field to be defined but also not defined at the same time... 🤯

I also can't imagine that it's nice to work with such an API, e.g. imagine:

  • You read the data of an existing entity over our admin API
  • You modify some value
  • You want to update that entity with the same payload

I think this was possible in the past (correct me if I'm wrong), but now you need to remove certain fields from your payload to send the update request, which is really annoying.

Of course in our administration codebase this is a non-issue, because there we use some extra logic / magic to build a changeset diff and only send that back to the server, but do you really expect every other API client to do the same or treat it differently like we do here in the migration? 😬

I would suggest either:

  1. Allowing updates in the DAL when the value of the Immutable field stays the same (is unchanged), as it should be in these cases like here in the "upsert" case for migration. Otherwise it would be a valid error if the migration tries to change such a value
  2. Or "silently" ignore that field in the DAL update case, without throwing an error. Maybe it should still create a log entry though 🤷‍♂️

I'm open for other suggestions as well, but I think we should have a better answer for the "upsert" case than just deal with it by throwing extra code at it. The Migration-Assistant makes heave use of "upsert" and basically writes all it's data that way:

$writeResults = $this->entityWriter->upsert(

cc: @patzick @keulinho what's your opinion on this?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That do makes sense, I was also thinking about the update should allow the payload with immutable key if the value doesn't change, but at the query time, we haven't aware of the current value in the database, fetching it before wouldn't be ideal, I will have a look further at this problem and your suggestion and provide an improvement for the flag.

For an external API consumer, I think ideally they don't want to send the whole entities; a subset of what changes is more practical and lightweight. But there might be cases where they want to resend the entire payload and catch the immutable error, as in your mentioned scenario.

Another simple option is to bypass the immutable check for system context scope; it will work for examples like MIG, but not if they update the entities via the admin api.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Allowing updates in the DAL when the value of the Immutable field stays the same (is unchanged), as it should be in these cases like here in the "upsert" case for migration. Otherwise it would be a valid error if the migration tries to change such a value

This should be possible, I added a draft PR here: shopware/shopware#14422

@tamvt tamvt requested a review from vienthuong January 20, 2026 02:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Compatible with migration assistant

5 participants