Benefits of using Uuid::fromStringToHex() in data migration or sync data from ERP system

March 18, 2024 - Reading time: 22 minutes

Cover Image

For more than four years working with Shopware 6, I have worked many times with data migration and syncing data from ERP systems. I realized that using Uuid::fromStringToHex() to generate an uuid for the data could make the process of building the import handling method faster and could avoid some bugs.

Here is the example code that I used three years ago to sync data from an ERP system to shopware, and it will help you understand the difference between using Uuid::randomHex(). I will give an example with property_group.

/**
* This is just a simple example to show how to create a property group and add an option to it
*/
public function syncPropertyGroup(Context $context): void
{
// STEP 1 - Start to create a group
$propertyNumberFromErp = 'SW-PROP-001'; // Data you got from ERP

// Assign an option to the group
$optionA = [
'id' => Uuid::randomHex(),
'name' => 'Option A',
'customFields' => [
'option_number_from_erp' => 'SW-OPT-001'
]
];

// Create property group ID
$groupId = Uuid::randomHex();

// Payload handled from ERP
$payload = [
'id' => $groupId,
'name' => '50lution - Hung Mac',
'options' => [$optionA],
'sorting_type' => PropertyGroupDefinition::SORTING_TYPE_ALPHANUMERIC,
'display_type' => PropertyGroupDefinition::DISPLAY_TYPE_TEXT,
'filterable' => true,
'customFields' => [
'property_number_from_erp' => $propertyNumberFromErp
]
];

$this->createGroup($payload, $context);
// END STEP 1

// STEP 2 ... a thousand years later
// You want to add another option to the group
// And now you got some data from the ERP like $propertyNumberFromErp and $optionB

// Assign an option to the group |--> Data you got from ERP
$optionB = [
'id' => Uuid::randomHex(),
'name' => 'Option B',
'customFields' => [
'option_number_from_erp' => 'SW-OPT-002'
]
];

// Update the group to add another option
$this->updateToAddAnotherOption($propertyNumberFromErp, $optionB, $context);
}

/**
* This method is called at the beginning
*/
private function createGroup(array $payload, Context $context): void
{
// Update property group
$this->propertyGroupRepository->create([$payload], $context);
}

/**
* This method is called after a thousand years
*/
private function updateToAddAnotherOption(string $propertyNumberFromErp, array $payloadOptions, Context $context): void
{
$payload = [
'options' => $payloadOptions
];

// You have to start to find the property group by property_number_from_erp
$criteria = new Criteria();
$criteria->addFilter(
new EqualsFilter('customFields.property_number_from_erp', $propertyNumberFromErp)
);

// Find the property group by property_number_from_erp
$foundId = $this->propertyGroupRepository->searchIds($criteria, $context)->firstId();
if (!is_string($foundId) || !Uuid::isValid($foundId)) {
// If the group is not found, you have to create a new group instead of updating

// TODO Handle payload for new group..
$payload['id'] = Uuid::randomHex();

$this->createGroup($payload, $context);
return;
}

$payload['id'] = $foundId;

$this->propertyGroupRepository->update($payload, $context);
}


As I commented in the code, this way of processing is too lengthy and requires checking the existence of data by property_number_from_erp to update, so if we apply using Uuid::fromStringToHex() it will be easy and more concise as the code below by combining with upsert.

/**
* This is just a simple example to show how to create a property group and add an option to it
*/
public function syncPropertyGroup(Context $context): void
{
// STEP 1 - Start to create a group
$propertyNumberFromErp = 'SW-PROP-001'; // Data you got from ERP

// Assign an option to the group
    $optionId = Uuid::fromStringToHex($groupId . '-SW-OPT-001');
    $optionA = [
'id' => $optionId,
'name' => 'Option A'
];

// Create property group ID from fromStringToHex
$groupId = Uuid::fromStringToHex($propertyNumberFromErp);

// Payload handled from ERP
$payload = [
'id' => $groupId,
'name' => '50lution - Hung Mac',
'options' => [$optionA],
'sorting_type' => PropertyGroupDefinition::SORTING_TYPE_ALPHANUMERIC,
'display_type' => PropertyGroupDefinition::DISPLAY_TYPE_TEXT,
'filterable' => true,
];

$this->createOrUpdateGroup($payload, $context);
// END STEP 1

// STEP 2 ... a thousand years later
// You want to add another option to the group
// And now you got some data from the ERP like $propertyNumberFromErp and $optionB
    // Assign an option to the group |--> Data you got from ERP
$optionId = Uuid::fromStringToHex($groupId . '-SW-OPT-002');
$optionB = [
'id' => $optionId,
'name' => 'Option B'
];

// I reused the payload here because it's the same above, just different options
$payload['options'] = [$optionA, $optionB];

// Update the group to add another option
$this->createOrUpdateGroup($payload, $context);
}

private function createOrUpdateGroup(array $payload, Context $context): void
{
// With upsert method, you can create a new group or update an existing group
$this->propertyGroupRepository->upsert([$payload], $context);
}

The difference here is that I removed property_number_from_erp in the customFields. Because the uuid is already identified by Uuid::fromStringToHex. Thanks to that, the UUID will always be the same when you pass the exact string from property_number_from_erp, so it is no longer necessary for us to find the UUID that exists with property_number_from_erp in custom fields.

Also, you will see I am using upsert() to create or update groups instead of create() or update() because the UUID is no longer random, so checking whether the data exists is no longer necessary.

Note: this is only suitable for shops that don't have any data yet or you're importing new data that isn't already in the store.