Install the Configurable Bundle feature
Edit on GitHubInstall feature core
Prerequisites
To start feature integration, overview, and install the necessary features:
NAME | VERSION |
---|---|
Spryker Core | 202404.0 |
Cart | 202404.0 |
Product | 202404.0 |
Product Lists | 202404.0 |
1) Install the required modules
Install the required modules using Composer:
composer require spryker-feature/configurable-bundle:"^202404.0" --update-with-dependencies
Make sure the following modules have been installed:
MODULE | EXPECTED DIRECTORY |
---|---|
ConfigurableBundle | spryker/configurable-bundle |
ConfigurableBundleGui | spryker/configurable-bundle-gui |
ConfigurableBundleGuiExtension | spryker/configurable-bundle-gui-extension |
ConfigurableBundleDataImport | spryker/configurable-bundle-data-import |
ConfigurableBundleStorage | spryker/configurable-bundle-storage |
ConfigurableBundlePageSearch | spryker/configurable-bundle-page-search |
SalesConfigurableBundle | spryker/sales-configurable-bundle |
ConfigurableBundleCart | spryker/configurable-bundle-cart |
ConfigurableBundlePage | spryker-shop/configurable-bundle-page |
2) Set up database schema and transfer objects
Adjust the schema definition so that entity changes will trigger the events:
src/Pyz/Zed/ConfigurableBundle/Persistence/Propel/Schema/spy_configurable_bundle.schema.xml
<?xml version="1.0"?>
<database xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
name="zed"
xsi:schemaLocation="spryker:schema-01 https://static.spryker.com/schema-01.xsd"
namespace="Orm\Zed\ConfigurableBundle\Persistence"
package="src.Orm.Zed.ConfigurableBundle.Persistence">
<table name="spy_configurable_bundle_template">
<behavior name="event">
<parameter name="spy_configurable_bundle_template_all" column="*"/>
</behavior>
</table>
<table name="spy_configurable_bundle_template_slot">
<behavior name="event">
<parameter name="spy_configurable_bundle_template_slot_all" column="*"/>
</behavior>
</table>
</database>
src/Pyz/Zed/ConfigurableBundleStorage/Persistence/Propel/Schema/spy_configurable_bundle_storage.schema.xml
<?xml version="1.0"?>
<database xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
name="zed"
xsi:schemaLocation="spryker:schema-01 https://static.spryker.com/schema-01.xsd"
namespace="Orm\Zed\ConfigurableBundleStorage\Persistence"
package="src.Orm.Zed.ConfigurableBundleStorage.Persistence">
<table name="spy_configurable_bundle_template_storage">
<behavior name="synchronization">
<parameter name="queue_pool" value="synchronizationPool" />
</behavior>
</table>
</database>
src/Pyz/Zed/ConfigurableBundlePageSearch/Persistence/Propel/Schema/spy_configurable_bundle_template_page_search.schema.xml
<?xml version="1.0"?>
<database xmlns="spryker:schema-01" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="zed" xsi:schemaLocation="spryker:schema-01 https://static.spryker.com/schema-01.xsd"
namespace="Orm\Zed\ConfigurableBundlePageSearch\Persistence"
package="src.Orm.Zed.ConfigurableBundlePageSearch.Persistence">
<table name="spy_configurable_bundle_template_page_search">
<behavior name="synchronization">
<parameter name="queue_pool" value="synchronizationPool"/>
</behavior>
</table>
</database>
Apply database changes and generate entity and transfer changes:
console propel:install
console transfer:generate
Make sure that the following changes have been applied by checking your database:
DATABASE ENTITY | TYPE | EVENT |
---|---|---|
spy_configurable_bundle_template | table | created |
spy_configurable_bundle_template_slot | table | created |
spy_sales_order_configured_bundle | table | created |
spy_sales_order_configured_bundle_item | table | created |
spy_configurable_bundle_template_storage | table | created |
spy_configurable_bundle_template_page_search | table | created |
Make sure the following changes have been applied in transfer objects:
TRANSFER | TYPE | EVENT | PATH |
---|---|---|---|
SpyConfigurableBundleTemplateEntity | class | created | src/Generated/Shared/Transfer/SpyConfigurableBundleTemplateEntityTransfer |
SpyConfigurableBundleTemplateSlotEntity | class | created | src/Generated/Shared/Transfer/SpyConfigurableBundleTemplateSlotEntityTransfer |
SpySalesOrderConfiguredBundleEntity | class | created | src/Generated/Shared/Transfer/SpySalesOrderConfiguredBundleEntityTransfer |
SpySalesOrderConfiguredBundleItemEntity | class | created | src/Generated/Shared/Transfer/SpySalesOrderConfiguredBundleItemEntityTransfer |
SpyConfigurableBundleTemplateStorageEntity | class | created | src/Generated/Shared/Transfer/SpyConfigurableBundleTemplateStorageEntityTransfer |
UpdateConfiguredBundleRequest` | class | created | src/Generated/Shared/Transfer/UpdateConfiguredBundleRequestTransfer |
SalesOrderConfiguredBundleTranslation | class | created | src/Generated/Shared/Transfer/SalesOrderConfiguredBundleTranslationTransfer |
ConfiguredBundle | class | created | src/Generated/Shared/Transfer/ConfiguredBundleTransfer |
ConfiguredBundleItem | class | created | src/Generated/Shared/Transfer/ConfiguredBundleItemTransfer |
ConfigurableBundleTemplate | class | created | src/Generated/Shared/Transfer/ConfigurableBundleTemplateTransfer |
ConfigurableBundleTemplateSlot | class | created | src/Generated/Shared/Transfer/ConfigurableBundleTemplateSlotTransfer |
ConfigurableBundleTemplateTranslation | class | created | src/Generated/Shared/Transfer/ConfigurableBundleTemplateTranslationTransfer |
ConfigurableBundleTemplateSlotTranslation | class | created | src/Generated/Shared/Transfer/ConfigurableBundleTemplateSlotTranslationTransfer |
ConfigurableBundleTemplateFilter | class | created | src/Generated/Shared/Transfer/ConfigurableBundleTemplateFilterTransfer |
ConfigurableBundleTemplateSlotFilter | class | created | src/Generated/Shared/Transfer/ConfigurableBundleTemplateSlotFilterTransfer |
ConfigurableBundleTemplateCollection | class | created | src/Generated/Shared/Transfer/ConfigurableBundleTemplateCollectionTransfer |
ConfigurableBundleTemplateSlotCollection | class | created | src/Generated/Shared/Transfer/ConfigurableBundleTemplateSlotCollectionTransfer |
ConfigurableBundleTemplateResponse | class | created | src/Generated/Shared/Transfer/ConfigurableBundleTemplateResponseTransfer |
ConfigurableBundleTemplateSlotResponse | class | created | src/Generated/Shared/Transfer/ConfigurableBundleTemplateSlotResponseTransfer |
ConfigurableBundleTemplateSlotEditForm | class | created | src/Generated/Shared/Transfer/ConfigurableBundleTemplateSlotEditFormTransfer |
ConfigurableBundleTemplateStorage | class | created | src/Generated/Shared/Transfer/ConfigurableBundleTemplateStorageTransfer |
ConfigurableBundleTemplateSlotStorage | class | created | src/Generated/Shared/Transfer/ConfigurableBundleTemplateSlotStorageTransfer |
ConfigurableBundleTemplatePageSearch | class | created | src/Generated/Shared/Transfer/ConfigurableBundleTemplatePageSearchTransfer |
ConfigurableBundleTemplatePageSearchCollection | class | created | src/Generated/Shared/Transfer/ConfigurableBundleTemplatePageSearchCollectionTransfer |
ConfigurableBundleTemplatePageSearchFilter | class | created | src/Generated/Shared/Transfer/ConfigurableBundleTemplatePageSearchFilterTransfer |
ConfigurableBundleTemplatePageSearchRequest | class | created | src/Generated/Shared/Transfer/ConfigurableBundleTemplatePageSearchRequestTransfer |
ProductListUsedByTable` | class | created | src/Generated/Shared/Transfer/ProductListUsedByTableTransfer |
ProductListUsedByTableRow | class | created | src/Generated/Shared/Transfer/ProductListUsedByTableRowTransfer |
ButtonCollection | class | created | src/Generated/Shared/Transfer/ButtonCollectionTransfer |
SalesOrderConfiguredBundleFilter | class | created | src/Generated/Shared/Transfer/SalesOrderConfiguredBundleFilterTransfer |
SalesOrderConfiguredBundleCollection | class | created | src/Generated/Shared/Transfer/SalesOrderConfiguredBundleCollectionTransfer |
SalesOrderConfiguredBundle | class | created | src/Generated/Shared/Transfer/SalesOrderConfiguredBundleTransfer` |
SalesOrderConfiguredBundleItem | class | created | src/Generated/Shared/Transfer/SalesOrderConfiguredBundleItemTransfer |
3) Add translations
Yves translations
Each configurable bundle template name needs to have Yves translations. Names are translated directly from spy_configurable_bundle_template.name
field, e.g.: configurable_bundle.templates.my-bundle.name
.
Same rule is applied for configurable bundle template slots: spy_configurable_bundle_template_slot.name
→ spy_configurable_bundle.template_slots.my-slot.name
Name is represented by a slugified version of a name for default locale, e.g.: Configurable Bundle “All In” → configurable-bundle-all-in
.
Append glossary according to your configuration:
src/data/import/glossary.csv
configured_bundle.quantity,Quantity:,en_US
configured_bundle.quantity,Anzahl:,de_DE
configured_bundle.price,Item price:,en_US
configured_bundle.price,Stückpreis:,de_DE
configured_bundle.bundle_total,Bundle total:,en_US
configured_bundle.bundle_total,Bündel Gesamt:,de_DE
configured_bundle.total,Item total:,en_US
configured_bundle.total,Artikel Gesamt:,de_DE
configured_bundle.remove,"× remove",en_US
configured_bundle.remove,"× entfernen",de_DE
configured_bundle.order.items,Items in the bundle:,en_US
configured_bundle.order.items,Produkte in diesem Bündel:,de_DE
configured_bundle.item_sku,SKU:,en_US
configured_bundle.item_sku,SKU:,de_DE
configurable_bundle.template.validation.error.not_exists,Configurable bundle template does not exist.,en_US
configurable_bundle.template.validation.error.not_exists,Vorlage des konfigurierbaren Bündels existiert nicht.,de_DE
configurable_bundle.slot.validation.error.not_exists,Configurable bundle template slot does not exist.,en_US
configurable_bundle.slot.validation.error.not_exists,Vorlagenslot des konfigurierbaren Bündels existiert nicht.,de_DE
configurable_bundle.template.validation.error.already_activated,Configurable bundle template is already activated.,en_US
configurable_bundle.template.validation.error.already_activated,Vorlage des konfigurierbaren Bündels wurde schon aktiviert.,de_DE
configurable_bundle.template.validation.error.already_deactivated,Configurable bundle template is already deactivated.,en_US
configurable_bundle.template.validation.error.already_deactivated,Vorlage des konfigurierbaren Bündels wurde schon deaktiviert.,de_DE
configured_bundle_cart.error.configured_bundle_cannot_be_added,Configured bundle cannot be added to cart.,en_US
configured_bundle_cart.error.configured_bundle_cannot_be_added,Configured bundle cannot be added to cart.,de_DE
configured_bundle_cart.error.configured_bundle_not_found,Configured bundle with provided sku not found in cart.,en_US
configured_bundle_cart.error.configured_bundle_not_found,Konfiguriertes Bundle mit mitgelieferter SKU nicht im Warenkorb gefunden.,de_DE
configured_bundle_cart.error.configured_bundle_cannot_be_removed,Configured bundle cannot be removed from cart.,en_US
configured_bundle_cart.error.configured_bundle_cannot_be_removed,Das konfigurierte Bundle kann nicht aus dem Warenkorb entfernt werden.,de_DE
configured_bundle_cart.error.configured_bundle_cannot_be_updated,Configured bundle cannot be updated.,en_US
configured_bundle_cart.error.configured_bundle_cannot_be_updated,Konfiguriertes Bundle kann nicht aktualisiert werden.,de_DE
configured_bundle_widget.configured_bundle.removed,Configured bundle removed successfully.,en_US
configured_bundle_widget.configured_bundle.removed,Konfiguriertes Bundle erfolgreich entfernt.,de_DE
configured_bundle_widget.configured_bundle.updated,Configured bundle updated successfully.,en_US
configured_bundle_widget.configured_bundle.updated,Konfiguriertes Bundle wurde erfolgreich aktualisiert.,de_DE
configurable_bundle_page.select,Select,en_US
configurable_bundle_page.select,Auswählen,de_DE
configurable_bundle_page.unselect,Unselect,en_US
configurable_bundle_page.unselect,Unselect,de_DE
configurable_bundle_page.edit,Edit,en_US
configurable_bundle_page.edit,Edit,de_DE
configurable_bundle_page.configurator,Configurator,en_US
configurable_bundle_page.configurator,Konfigurator,de_DE
configurable_bundle_page.configurable_bundle_list,Configurable Bundle List,en_US
configurable_bundle_page.configurable_bundle_list,Configurable Bundle List,de_DE
configurable_bundle_page.choose_bundle_to_configure,Choose Bundle to configure,en_US
configurable_bundle_page.choose_bundle_to_configure,Choose Bundle to configure,de_DE
configurable_bundle_page.configurator.templates_not_found,There are no templates available.,en_US
configurable_bundle_page.configurator.templates_not_found,There are no templates available.,de_DE
configurable_bundle_page.template_not_found,Configurable bundle template not found.,en_US
configurable_bundle_page.template_not_found,Configurable bundle template not found.,de_DE
configurable_bundle_page.invalid_template_slot_combination,Invalid template/slot combination.,en_US
configurable_bundle_page.invalid_template_slot_combination,Invalid template/slot combination.,de_DE
configurable_bundle_page.configurator.tip.header,Create your own bundle.,en_US
configurable_bundle_page.configurator.tip.header,Create your own bundle.,de_DE
configurable_bundle_page.configurator.tip.text,"To create the bundle, please select the slot from the left side, and choose the product from the list.",en_US
configurable_bundle_page.configurator.tip.text,"To create the bundle, please select the slot from the left side, and choose the product from the list.",de_DE
configurable_bundle_page.configurator.selected_product,Selected product,en_US
configurable_bundle_page.configurator.selected_product,Selected product,de_DE
configurable_bundle_page.configurator.summary,Summary,en_US
configurable_bundle_page.configurator.summary,Summary,de_DE
configurable_bundle_page.configurator.add_to_cart,Add to Cart,en_US
configurable_bundle_page.configurator.add_to_cart,Add to Cart,de_DE
configurable_bundle_page.configurator.summary_page_locked,Product for at least one slot should be configured to visit Summary page.,en_US
configurable_bundle_page.configurator.summary_page_locked,Product for at least one slot should be configured to visit Summary page.,de_DE
configurable_bundle_page.configurator.summary_page_total,Total,en_US
configurable_bundle_page.configurator.summary_page_total,Gesamt,de_DE
configurable_bundle_page.configurator.added_to_cart,Configured bundle successfully added to cart.,en_US
configurable_bundle_page.configurator.added_to_cart,Configured bundle successfully added to cart.,de_DE
configurable_bundle_page.configurator.slot_became_unavailable,Configured slot with ID '%id%' became unavailable.,en_US
configurable_bundle_page.configurator.slot_became_unavailable,Configured slot with ID '%id%' became unavailable.,de_DE
configurable_bundle_page.configurator.product_became_unavailable,Product with SKU '%sku%' configured for slot with ID '%id%' became unavailable.,en_US
configurable_bundle_page.configurator.product_became_unavailable,Product with SKU '%sku%' configured for slot with ID '%id%' became unavailable.,de_DE
Please note, that if you have any configurable bundle entities already present or coming from data import, then you’ll also need to provide translations for templates and slots as given in example below.
src/data/import/glossary.csv
configurable_bundle.templates.configurable-bundle-all-in.name,"Configurable Bundle ""All in""",en_US
configurable_bundle.templates.configurable-bundle-all-in.name,"Konfigurierbares Bündel ""All in""",de_DE
configurable_bundle.templates.smartstation.name,Smartstation Kit,en_US
configurable_bundle.templates.smartstation.name,Smartstation-Kit,de_DE
configurable_bundle.template_slots.slot-1.name,Slot 1,en_US
configurable_bundle.template_slots.slot-1.name,Slot 1,de_DE
configurable_bundle.template_slots.slot-2.name,Slot 2,en_US
configurable_bundle.template_slots.slot-2.name,Slot 2,de_DE
configurable_bundle.template_slots.slot-3.name,Slot 3,en_US
configurable_bundle.template_slots.slot-3.name,Slot 3,de_DE
configurable_bundle.template_slots.slot-4.name,Slot 4,en_US
configurable_bundle.template_slots.slot-4.name,Slot 4,de_DE
configurable_bundle.template_slots.slot-5.name,Slot 5,en_US
configurable_bundle.template_slots.slot-5.name,Slot 5,de_DE
configurable_bundle.template_slots.slot-6.name,Slot 6,en_US
configurable_bundle.template_slots.slot-6.name,Slot 6,de_DE
Import data:
console data:import glossary
Make sure that, in the database, the configured data are added to the spy_glossary
table.
Zed translations
Run the following command to generate a new translation cache for Zed:
console translator:generate-cache
Make sure that when you make an order from a cart with a configured bundles, bundle name is translated on the order page in Zed.
4) Set up search
Add the page map plugin for the configurable bundle template entity.
PLUGIN | SPECIFICATION | PREREQUISITES | NAMESPACE |
---|---|---|---|
ConfigurableBundleTemplatePageMapPlugin | Builds page map for configurable bundle template entity | None | Spryker\Zed\ConfigurableBundlePageSearch\Communication\Plugin\Search |
src/Pyz/Zed/Search/SearchDependencyProvider.php
<?php
namespace Pyz\Zed\Search;
use Spryker\Zed\ConfigurableBundlePageSearch\Communication\Plugin\Search\ConfigurableBundleTemplatePageMapPlugin;
use Spryker\Zed\Search\SearchDependencyProvider as SprykerSearchDependencyProvider;
class SearchDependencyProvider extends SprykerSearchDependencyProvider
{
/**
* @return \Spryker\Zed\Search\Dependency\Plugin\PageMapInterface[]
*/
protected function getSearchPageMapPlugins()
{
return [
new ConfigurableBundleTemplatePageMapPlugin(),
];
}
}
Add query expander and result-formatter plugins for the configurable bundle template entity.
PLUGIN | SPECIFICATION | PREREQUISITES | NAMESPACE |
---|---|---|---|
ConfigurableBundleTemplatePageSearchResultFormatterPlugin | Maps raw search results from Elasticsearch to a transfer and returns the formatted result. | None | Spryker\Client\ConfigurableBundlePageSearch\Plugin\Elasticsearch\ResultFormatter |
LocalizedQueryExpanderPlugin | Adds filtering by locale to search query. | None | Spryker\Client\Search\Plugin\Elasticsearch\QueryExpander |
src/Pyz/Client/ConfigurableBundlePageSearch/ConfigurableBundlePageSearchDependencyProvider.php
<?php
namespace Pyz\Client\ConfigurableBundlePageSearch;
use Spryker\Client\ConfigurableBundlePageSearch\ConfigurableBundlePageSearchDependencyProvider as SprykerConfigurableBundlePageSearchDependencyProvider;
use Spryker\Client\ConfigurableBundlePageSearch\Plugin\Elasticsearch\ResultFormatter\ConfigurableBundleTemplatePageSearchResultFormatterPlugin;
use Spryker\Client\Search\Plugin\Elasticsearch\QueryExpander\LocalizedQueryExpanderPlugin;
class ConfigurableBundlePageSearchDependencyProvider extends SprykerConfigurableBundlePageSearchDependencyProvider
{
/**
* @return \Spryker\Client\Search\Dependency\Plugin\ResultFormatterPluginInterface[]
*/
protected function getConfigurableBundleTemplatePageSearchResultFormatterPlugins(): array
{
return [
new ConfigurableBundleTemplatePageSearchResultFormatterPlugin(),
];
}
/**
* @return \Spryker\Client\Search\Dependency\Plugin\QueryExpanderPluginInterface[]
*/
protected function getConfigurableBundleTemplatePageSearchQueryExpanderPlugins(): array
{
return [
new LocalizedQueryExpanderPlugin(),
];
}
}
5) Configure export to Redis and Elasticsearch
This step will publish tables on change (create, edit) to the spy_configurable_bundle_template_storage and synchronize the data to Storage.
Set up event listeners
PLUGIN | SPECIFICATION | PREREQUISITES | NAMESPACE |
---|---|---|---|
ConfigurableBundleStorageEventSubscriber | Registers listeners that are responsible for publishing configurable bundle storage template entity changes when a related entity change event occurs. | None | Spryker\Zed\ConfigurableBundleStorage\Communication\Plugin\Event\Subscriber |
ConfigurableBundleTemplatePageSearchEventSubscriber | Registers listeners that are responsible for publishing configurable bundle storage template entity changes to search when a related entity change event occurs. | None | Spryker\Zed\ConfigurableBundlePageSearch\Communication\Plugin\Event\Subscriber |
src/Pyz/Zed/Event/EventDependencyProvider.php
<?php
namespace Pyz\Zed\Event;
use Spryker\Zed\ConfigurableBundlePageSearch\Communication\Plugin\Event\Subscriber\ConfigurableBundleTemplatePageSearchEventSubscriber;
use Spryker\Zed\Event\EventDependencyProvider as SprykerEventDependencyProvider;
use Spryker\Zed\ConfigurableBundleStorage\Communication\Plugin\Event\Subscriber\ConfigurableBundleStorageEventSubscriber;
<details>
<summary></summary>
Your text
<br>
</details>
class EventDependencyProvider extends SprykerEventDependencyProvider
{
public function getEventSubscriberCollection()
{
$eventSubscriberCollection = parent::getEventSubscriberCollection();
$eventSubscriberCollection->add(new ConfigurableBundleStorageEventSubscriber());
$eventSubscriberCollection->add(new ConfigurableBundleTemplatePageSearchEventSubscriber());
return $eventSubscriberCollection;
}
}
Register the synchronization queue and synchronization error queue
src/Pyz/Client/RabbitMq/RabbitMqConfig.php
<?php
namespace Pyz\Client\RabbitMq;
use ArrayObject;
use Spryker\Client\RabbitMq\RabbitMqConfig as SprykerRabbitMqConfig;
use Spryker\Shared\ConfigurableBundlePageSearch\ConfigurableBundlePageSearchConfig;
use Spryker\Shared\ConfigurableBundleStorage\ConfigurableBundleStorageConfig;
class RabbitMqConfig extends SprykerRabbitMqConfig
{
/**
* @return \ArrayObject
*/
protected function getQueueOptions()
{
$queueOptionCollection = new ArrayObject();
$queueOptionCollection->append($this->createQueueOption(ConfigurableBundleStorageConfig::CONFIGURABLE_BUNDLE_SYNC_STORAGE_QUEUE, ConfigurableBundleStorageConfig::CONFIGURABLE_BUNDLE_SYNC_STORAGE_ERROR_QUEUE));
$queueOptionCollection->append($this->createQueueOption(ConfigurableBundlePageSearchConfig::CONFIGURABLE_BUNDLE_SEARCH_QUEUE, ConfigurableBundlePageSearchConfig::CONFIGURABLE_BUNDLE_SEARCH_ERROR_QUEUE));
return $queueOptionCollection;
}
}
Configure message processors
src/Pyz/Zed/Queue/QueueDependencyProvider.php
<?php
namespace Pyz\Zed\Queue;
use Spryker\Shared\ConfigurableBundlePageSearch\ConfigurableBundlePageSearchConfig;
use Spryker\Shared\ConfigurableBundleStorage\ConfigurableBundleStorageConfig;
use Spryker\Zed\Kernel\Container;
use Spryker\Zed\Queue\QueueDependencyProvider as SprykerDependencyProvider;
use Spryker\Zed\Synchronization\Communication\Plugin\Queue\SynchronizationSearchQueueMessageProcessorPlugin;
use Spryker\Zed\Synchronization\Communication\Plugin\Queue\SynchronizationStorageQueueMessageProcessorPlugin;
class QueueDependencyProvider extends SprykerDependencyProvider
{
/**
* @param \Spryker\Zed\Kernel\Container $container
*
* @return \Spryker\Zed\Queue\Dependency\Plugin\QueueMessageProcessorPluginInterface[]
*/
protected function getProcessorMessagePlugins(Container $container)
{
return [
ConfigurableBundleStorageConfig::CONFIGURABLE_BUNDLE_SYNC_STORAGE_QUEUE => new SynchronizationStorageQueueMessageProcessorPlugin(),
ConfigurableBundlePageSearchConfig::CONFIGURABLE_BUNDLE_SEARCH_QUEUE => new SynchronizationSearchQueueMessageProcessorPlugin(),
];
}
}
Set up re-generate and re-sync features
PLUGIN | SPECIFICATION | PREREQUISITES | NAMESPACE |
---|---|---|---|
ConfigurableBundleTemplateEventResourceBulkRepositoryPlugin | Allows populating empty storage table with data. | None | Spryker\Zed\ConfigurableBundleStorage\Communication\Plugin\Event |
ConfigurableBundleTemplatePageSearchEventResourceBulkRepositoryPlugin | Allows populating empty search table with data. | None | Spryker\Zed\ConfigurableBundleStorage\Communication\Plugin\Event |
ConfigurableBundleTemplateSynchronizationDataBulkPlugin | Allows synchronizing the entire storage table content into Storage. | None | Spryker\Zed\ConfigurableBundleStorage\Communication\Plugin\Synchronization |
ConfigurableBundleTemplatePageSynchronizationDataBulkPlugin | Allows synchronizing all of the content into Search. | None | Spryker\Zed\ConfigurableBundlePageSearch\Communication\Plugin\Synchronization |
src/Pyz/Zed/EventBehavior/EventBehaviorDependencyProvider.php
<?php
namespace Pyz\Zed\EventBehavior;
use Spryker\Zed\ConfigurableBundlePageSearch\Communication\Plugin\Event\ConfigurableBundleTemplatePageSearchEventResourceBulkRepositoryPlugin;
use Spryker\Zed\ConfigurableBundleStorage\Communication\Plugin\Event\ConfigurableBundleTemplateEventResourceBulkRepositoryPlugin;
use Spryker\Zed\EventBehavior\EventBehaviorDependencyProvider as SprykerEventBehaviorDependencyProvider;
class EventBehaviorDependencyProvider extends SprykerEventBehaviorDependencyProvider
{
/**
* @return \Spryker\Zed\EventBehavior\Dependency\Plugin\EventResourcePluginInterface[]
*/
protected function getEventTriggerResourcePlugins()
{
return [
new ConfigurableBundleTemplateEventResourceBulkRepositoryPlugin(),
new ConfigurableBundleTemplatePageSearchEventResourceBulkRepositoryPlugin(),
];
}
}
src/Pyz/Zed/Synchronization/SynchronizationDependencyProvider.php
<?php
namespace Pyz\Zed\Synchronization;
use Spryker\Zed\ConfigurableBundleStorage\Communication\Plugin\Synchronization\ConfigurableBundleTemplateSynchronizationDataBulkPlugin;
use Spryker\Zed\ConfigurableBundlePageSearch\Communication\Plugin\Synchronization\ConfigurableBundleTemplatePageSynchronizationDataBulkPlugin;
use Spryker\Zed\Synchronization\SynchronizationDependencyProvider as SprykerSynchronizationDependencyProvider;
class SynchronizationDependencyProvider extends SprykerSynchronizationDependencyProvider
{
/**
* @return \Spryker\Zed\SynchronizationExtension\Dependency\Plugin\SynchronizationDataPluginInterface[]
*/
protected function getSynchronizationDataPlugins(): array
{
return [
new ConfigurableBundleTemplateSynchronizationDataBulkPlugin(),
new ConfigurableBundleTemplatePageSynchronizationDataBulkPlugin(),
];
}
}
Configure synchronization pool name
src/Pyz/Zed/ConfigurableBundleStorage/ConfigurableBundleStorageConfig.php
<?php
namespace Pyz\Zed\ConfigurableBundleStorage;
use Pyz\Zed\Synchronization\SynchronizationConfig;
use Spryker\Zed\ConfigurableBundleStorage\ConfigurableBundleStorageConfig as SprykerConfigurableBundleStorageConfig;
class ConfigurableBundleStorageConfig extends SprykerConfigurableBundleStorageConfig
{
/**
* @return string|null
*/
public function getConfigurableBundleTemplateSynchronizationPoolName(): ?string
{
return SynchronizationConfig::DEFAULT_SYNCHRONIZATION_POOL_NAME;
}
}
src/Pyz/Zed/ConfigurableBundlePageSearch/ConfigurableBundlePageSearchConfig.php
<?php
namespace Pyz\Zed\ConfigurableBundlePageSearch;
use Pyz\Zed\Synchronization\SynchronizationConfig;
use Spryker\Zed\ConfigurableBundlePageSearch\ConfigurableBundlePageSearchConfig as SprykerConfigurableBundlePageSearch;
class ConfigurableBundlePageSearchConfig extends SprykerConfigurableBundlePageSearch
{
/**
* @return string|null
*/
public function getConfigurableBundlePageSynchronizationPoolName(): ?string
{
return SynchronizationConfig::DEFAULT_SYNCHRONIZATION_POOL_NAME;
}
}
-
Make sure that when you added some data to tables
spy_configurable_bundle_template
orspy_configurable_bundle_template_slot
and runconsole trigger:event -r configurable_bundle_template
command, the changes reflect inspy_configurable_bundle_template_storage
andspy_configurable_bundle_template_page_search
tables. -
Make sure that after step #1 or after command
console sync:data configurable_bundle_template
execution data is exported:
- from
spy_configurable_bundle_template_storage
table to Redis - from
spy_configurable_bundle_template_page_search
table to Elasticsearch
- Make sure that when a configurable bundle template (or template slot) created or edited through ORM, it is exported to Redis or Elasticsearch accordingly.
STORAGE TYPE | TARGET ENTITY | EXAMPLE EXPECTED DATA IDENTIFIER |
---|---|---|
Redis | ConfigurableBundleTemplate | kv:configurable_bundle_template:1 |
Elasticsearch | ConfigurableBundleTemplate | configurable_bundle_template:en_us:1 |
Example expected data fragment for Redis
{
"id_configurable_bundle_template": 2,
"uuid": "c8291fd3-c6ca-5b8f-8ff5-eccd6cb787de",
"name": "configurable_bundle_templates.my-bundle.name",
"slots": [
[
"id_configurable_bundle_template_slot": 6,
"uuid": 9626de80-6caa-57a9-a683-2846ec5b6914,
"name": "configurable_bundle.template_slots.slot-6.name",
"id_product_list": 13
],
[
"id_configurable_bundle_template_slot": 7,
"uuid": 2a5e55b1-993a-5510-864c-a4a18558aa75,
"name": "configurable_bundle.template_slots.slot-7.name",
"id_product_list": 14
]
]
}
Example expected data fragment for Elasticsearch
{
"locale":"en_US",
"type":"configurable_bundle_template",
"search-result-data":{
"idConfigurableBundleTemplate":1,
"uuid":"8d8510d8-59fe-5289-8a65-19f0c35a0089",
"name":"configurable_bundle.templates.configurable-bundle-all-in.nam"
}
}
6) Import data
Import configurable bundles data
Prepare your data according to your requirements using our demo data:
vendor/spryker/spryker/Bundles/ConfigurableBundleDataImport/data/import/configurable_bundle_template.csv
configurable_bundle_template_key,configurable_bundle_template_uuid,configurable_bundle_template_name,configurable_bundle_template_is_active
t000001,8d8510d8-59fe-5289-8a65-19f0c35a0089,configurable_bundle.templates.configurable-bundle-all-in.name,1
t000002,c8291fd3-c6ca-5b8f-8ff5-eccd6cb787de,configurable_bundle.templates.smartstation.name,1
COLUMN | REQUIRED | DATA TYPE | DATA EXAMPLE | DATA EXPLANATION |
---|---|---|---|---|
configurable_bundle_template_key | ✓ | string | t000001 | Internal data import identifier for the configurable bundle template. |
configurable_bundle_template_uuid | optional | string | 8d8510d8-59fe-5289-8a65-19f0c35a0089 | Unique identifier for the configurable bundle. |
configurable_bundle_template_name | ✓ | string | configurable_bundle.templates.smartstation.name | Glossary key for the configurable bundle name. |
configurable_bundle_template_is_active | ✓ | bool | 1 | IsActive flag for the configurable bundle name. |
vendor/spryker/spryker/Bundles/ConfigurableBundleDataImport/data/import/configurable_bundle_template_slot.csv
configurable_bundle_template_slot_key,configurable_bundle_template_slot_name,configurable_bundle_template_slot_uuid,configurable_bundle_template_key,product_list_key
s000001,configurable_bundle.template_slots.slot-1.name,332b40ac-a789-57ce-bec0-23d8dddd71eb,t000001,pl-009
s000002,configurable_bundle.template_slots.slot-2.name,a7599d6b-9453-54b9-81d3-60a81effa883,t000001,pl-010
s000003,configurable_bundle.template_slots.slot-3.name,81cd2899-00aa-5da8-92df-374df8fcc72a,t000001,pl-011
s000004,configurable_bundle.template_slots.slot-4.name,c5f76e16-401e-56ba-9126-ac228d16f055,t000001,pl-012
s000005,configurable_bundle.template_slots.slot-5.name,9626de80-6caa-57a9-a683-2846ec5b6914,t000002,pl-013
s000006,configurable_bundle.template_slots.slot-6.name,2a5e55b1-993a-5510-864c-a4a18558aa75,t000002,pl-014
COLUMN | REQUIRED | DATA TYPE | DATA EXAMPLE | DATA EXPLANATION |
---|---|---|---|---|
configurable_bundle_template_slot_key | ✓ | string | s000001 | Internal data import identifier for the configurable bundle template slot. |
configurable_bundle_template_slot_name | ✓ | string | configurable_bundle.template_slots.slot-1.name | Name (glossary key) for the configurable bundle template slot. |
configurable_bundle_template_slot_uuid | optional | string | 332b40ac-a789-57ce-bec0-23d8dddd71eb | Unique identifier for the configurable bundle template slot. |
configurable_bundle_template_key | ✓ | string | t000001 | Internal data import identifier for the configurable bundle template. |
product_list_key | ✓ | string | pl-009 | The ID of the product list for allowed products of the slot. |
Register the following plugins to enable data import:
PLUGIN | SPECIFICATION | PREREQUISITES | NAMESPACE |
---|---|---|---|
ConfigurableBundleTemplateDataImportPlugin | Imports configurable bundle template data into the database. | None | Spryker\Zed\ConfigurableBundleDataImport\Communication\Plugin |
ConfigurableBundleTemplateSlotDataImportPlugin | Imports configurable bundle template slot data into the database. | None | Spryker\Zed\ConfigurableBundleDataImport\Communication\Plugin |
src/Pyz/Zed/DataImport/DataImportDependencyProvider.php
<?php
namespace Pyz\Zed\DataImport;
use Spryker\Zed\DataImport\DataImportDependencyProvider as SprykerDataImportDependencyProvider;
use Spryker\Zed\ConfigurableBundleDataImport\Communication\Plugin\ConfigurableBundleTemplateDataImportPlugin;
use Spryker\Zed\ConfigurableBundleDataImport\Communication\Plugin\ConfigurableBundleTemplateSlotDataImportPlugin;
class DataImportDependencyProvider extends SprykerDataImportDependencyProvider
{
protected function getDataImporterPlugins(): array
{
return [
new ConfigurableBundleTemplateDataImportPlugin(),
new ConfigurableBundleTemplateSlotDataImportPlugin(),
];
}
}
Import data:
console data:import configurable-bundle-template
console data:import configurable-bundle-template-slot
Make sure that the configurable bundle data is added to the spy_configurable_bundle_template
, spy_configurable_bundle_template_slot
tables in the database.
To add a new point into navigation, adjust import data:
data/import/navigation_node.csv
navigation_key,node_key,parent_node_key,node_type,title.en_US,url.en_US,css_class.en_US,title.de_DE,url.de_DE,css_class.de_DE,valid_from,valid_to
MAIN_NAVIGATION,node_key_48,node_key_18,link,Configurable Bundle List,/en/configurable-bundle/configurator/template-selection,,Configurable Bundle List,/de/configurable-bundle/configurator/template-selection,,,
Don’t forget to replace sample node keys with ones relevant for your project.
Run the following command to import data:
console data:import navigation-node
Navigate to your shop and make sure you can see a new item in the navigation menu.
7) Set up behavior
Set up configurable bundles workflow
Enable the following behaviors by registering the plugins:
PLUGIN | SPECIFICATION | PREREQUISITES | NAMESPACE |
---|---|---|---|
ConfiguredBundleOrderExpanderPlugin | Expands sales order by configured bundles. Expands ItemTransfer by configured bundle item. | None | Spryker\Zed\SalesConfigurableBundle\Communication\Plugin\Sales |
ConfiguredBundlesOrderPostSavePlugin | Persists configured bundles from ItemTransfer in Quote to sales_order configured bundle tables. |
None | Spryker\Zed\SalesConfigurableBundle\Communication\Plugin\Sales |
src/Pyz/Zed/Sales/SalesDependencyProvider.php
<?php
namespace Pyz\Zed\Sales;
use Spryker\Zed\Sales\SalesDependencyProvider as SprykerSalesDependencyProvider;
use Spryker\Zed\SalesConfigurableBundle\Communication\Plugin\Sales\ConfiguredBundleOrderExpanderPlugin;
use Spryker\Zed\SalesConfigurableBundle\Communication\Plugin\Sales\ConfiguredBundlesOrderPostSavePlugin;
class SalesDependencyProvider extends SprykerSalesDependencyProvider
{
/**
* @return \Spryker\Zed\SalesExtension\Dependency\Plugin\OrderExpanderPluginInterface[]
*/
protected function getOrderHydrationPlugins()
{
return [
new ConfiguredBundleOrderExpanderPlugin(),
];
}
/**
* @return \Spryker\Zed\SalesExtension\Dependency\Plugin\OrderPostSavePluginInterface[]
*/
protected function getOrderPostSavePlugins()
{
return [
new ConfiguredBundlesOrderPostSavePlugin(),
];
}
}
Make sure that when you place an order with a configured bundle:
- New data saved to
spy_sales_order_configured_bundle_item
andspy_sales_order_configured_bundle
. - You can see items grouped by configured bundle details on the order details page in Yves. (You can access it by clicking View Order here
http://mysprykershop.com/customer/overview
)
Register Pre-load, Pre-check and Expander Plugins for the Cart Module
PLUGIN | SPECIFICATION | PREREQUISITES | NAMESPACE |
---|---|---|---|
CartConfigurableBundlePreReloadPlugin | Removes items from the QuoteTransfer if its configurable bundle template was removed or became inactive. | None | Spryker\Zed\ConfigurableBundle\Communication\Plugin\Cart |
ConfiguredBundleQuantityPostSavePlugin | Applies to items that have configurable properties. Updates configured bundle quantity. | None | Spryker\Zed\ConfigurableBundleCart\Communication\Plugin\Cart |
ConfiguredBundleQuantityPerSlotPreReloadItemsPlugin | Applies to items that have configurable properties. Updates configured bundle quantity per slot. | None | Spryker\Zed\ConfigurableBundleCart\Communication\Plugin\Cart |
ConfiguredBundleQuantityCartTerminationPlugin | Terminates add/remove product to the cart process if configured bundle quantity is not proportional to product quantity. | None | Spryker\Zed\ConfigurableBundleCart\Communication\Plugin\Cart |
ConfiguredBundleTemplateSlotCombinationPreCheckPlugin | Checks configurable bundle template/slot combinations. Adds error message if wrong combinations found. | None | Spryker\Zed\ConfigurableBundleCart\Communication\Plugin\Cart |
ConfiguredBundleQuantityPerSlotItemExpanderPlugin | Expands configured bundle items with the quantity per slot. | None | Spryker\Zed\ConfigurableBundleCart\Communication\Plugin\Cart |
ConfiguredBundleGroupKeyItemExpanderPlugin | Expands items with configured bundle property with the group key. | None | Spryker\Zed\ConfigurableBundleCart\Communication\Plugin\Cart |
src/Pyz/Zed/Cart/CartDependencyProvider.php
<?php
namespace Pyz\Zed\Cart;
use Spryker\Zed\Cart\CartDependencyProvider as SprykerCartDependencyProvider;
use Spryker\Zed\ConfigurableBundle\Communication\Plugin\Cart\CartConfigurableBundlePreReloadPlugin;
use Spryker\Zed\ConfigurableBundleCart\Communication\Plugin\Cart\ConfiguredBundleGroupKeyItemExpanderPlugin;
use Spryker\Zed\ConfigurableBundleCart\Communication\Plugin\Cart\ConfiguredBundleQuantityPerSlotItemExpanderPlugin;
use Spryker\Zed\ConfigurableBundleCart\Communication\Plugin\Cart\ConfiguredBundleTemplateSlotCombinationPreCheckPlugin;
use Spryker\Zed\ConfigurableBundleCart\Communication\Plugin\Cart\ConfiguredBundleQuantityCartTerminationPlugin;
use Spryker\Zed\ConfigurableBundleCart\Communication\Plugin\Cart\ConfiguredBundleQuantityPerSlotPreReloadItemsPlugin;
use Spryker\Zed\ConfigurableBundleCart\Communication\Plugin\Cart\ConfiguredBundleQuantityPostSavePlugin;
use Spryker\Zed\Kernel\Container;
class CartDependencyProvider extends SprykerCartDependencyProvider
{
/**
* @param \Spryker\Zed\Kernel\Container $container
*
* @return \Spryker\Zed\CartExtension\Dependency\Plugin\PreReloadItemsPluginInterface[]
*/
protected function getPreReloadPlugins(Container $container)
{
return [
new CartConfigurableBundlePreReloadPlugin(),
new ConfiguredBundleQuantityPerSlotPreReloadItemsPlugin(),
];
}
/**
* @param \Spryker\Zed\Kernel\Container $container
*
* @return \Spryker\Zed\Cart\Dependency\ItemExpanderPluginInterface[]
* @return \Spryker\Zed\CartExtension\Dependency\Plugin\ItemExpanderPluginInterface[]
*/
protected function getExpanderPlugins(Container $container)
{
return [
new ConfiguredBundleQuantityPerSlotItemExpanderPlugin(),
new ConfiguredBundleGroupKeyItemExpanderPlugin(),
];
}
/**
* @param \Spryker\Zed\Kernel\Container $container
*
* @return \Spryker\Zed\CartExtension\Dependency\Plugin\CartPreCheckPluginInterface[]
*/
protected function getCartPreCheckPlugins(Container $container)
{
return [
new ConfiguredBundleTemplateSlotCombinationPreCheckPlugin(),
];
}
/**
* @param \Spryker\Zed\Kernel\Container $container
*
* @return \Spryker\Zed\CartExtension\Dependency\Plugin\CartOperationPostSavePluginInterface[]
*/
protected function getPostSavePlugins(Container $container)
{
return [
new ConfiguredBundleQuantityPostSavePlugin(),
];
}
/**
* @param \Spryker\Zed\Kernel\Container $container
*
* @return \Spryker\Zed\CartExtension\Dependency\Plugin\CartTerminationPluginInterface[]
*/
protected function getTerminationPlugins(Container $container)
{
return [
new ConfiguredBundleQuantityCartTerminationPlugin(),
];
}
}
Make sure that deleted or deactivated configured bundles are removed from the cart.
Make sure after updating the configured bundle quantity on cart page:
- The quantity of each item in the bundle has changed.
- The quantity of bundle has changed.
- Make clean up for the configured bundle item (in
session/database
storage):$itemTransfer->getConfiguredBundleItem()->setQuantityPerSlot(null)
; - Reload cart page;
- Make sure that
ConfiguredBundleItem::quantityPerSlot
is not null.
- Set the wrong quantity to
ConfiguredBundle::quantity
for the configured bundle item. - Make sure that after updating the configured bundle quantity on cart page error flash message shown.
Register Delete Pre-Check Plugins for the ProductList Module
PLUGIN | SPECIFICATION | PREREQUISITES | NAMESPACE |
---|---|---|---|
ConfigurableBundleTemplateSlotProductListDeletePreCheckPlugin | Finds configurable bundle template slots that use a given Product List. Disallows Product List deleting if any usage cases found. | None | Spryker\Zed\ConfigurableBundle\Communication\Plugin\ProductList |
src/Pyz/Zed/ProductList/ProductListDependencyProvider.php
<?php
namespace Pyz\Zed\ProductList;
use Spryker\Zed\ConfigurableBundle\Communication\Plugin\ProductList\ConfigurableBundleTemplateSlotProductListDeletePreCheckPlugin;
use Spryker\Zed\ProductList\ProductListDependencyProvider as SprykerProductListDependencyProvider;
class ProductListDependencyProvider extends SprykerProductListDependencyProvider
{
/**
* @return \Spryker\Zed\ProductListExtension\Dependency\Plugin\ProductListDeletePreCheckPluginInterface[]
*/
protected function getProductListDeletePreCheckPlugins(): array
{
return [
new ConfigurableBundleTemplateSlotProductListDeletePreCheckPlugin(),
];
}
}
Make sure an error occurs while deleting a product list that was assigned to a slot.
8) Configure Zed UI
Register plugins for the ConfigurableBundleGui module
PLUGIN | SPECIFICATION | PREREQUISITES | NAMESPACE |
---|---|---|---|
ProductListManagementConfigurableBundleTemplateSlotEditTabsExpanderPlugin | Expands Slot Edit page tabs with additional product list management tabs. | None | Spryker\Zed\ProductListGui\Communication\Plugin\ConfigurableBundleGui |
ProductListManagementConfigurableBundleTemplateSlotEditFormExpanderPlugin | Expands Slot Edit form with Product List assignment subforms. | None | Spryker\Zed\ProductListGui\Communication\Plugin\ConfigurableBundleGui |
ProductListManagementConfigurableBundleTemplateSlotEditFormDataProviderExpanderPlugin | Expands options for Slot Edit form with Product List management data. | None | Spryker\Zed\ProductListGui\Communication\Plugin\ConfigurableBundleGui |
ProductConcreteRelationCsvConfigurableBundleTemplateSlotEditFormFileUploadHandlerPlugin | Handles Product Concrete Relation CSV file upload. | None | Spryker\Zed\ProductListGui\Communication\Plugin\ConfigurableBundleGui |
ProductConcreteRelationConfigurableBundleTemplateSlotEditSubTabsProviderPlugin | Provides subtabs for the Assign Products tab. | None | Spryker\Zed\ProductListGui\Communication\Plugin\ConfigurableBundleGui |
ProductConcreteRelationConfigurableBundleTemplateSlotEditTablesProviderPlugin | Provides tables for the Assign Products tab. | None | Spryker\Zed\ProductListGui\Communication\Plugin\ConfigurableBundleGui |
src/Pyz/Zed/ConfigurableBundleGui/ConfigurableBundleGuiDependencyProvider.php
<?php
namespace Pyz\Zed\ConfigurableBundleGui;
use Spryker\Zed\ConfigurableBundleGui\ConfigurableBundleGuiDependencyProvider as SprykerConfigurableBundleGuiDependencyProvider;
use Spryker\Zed\ProductListGui\Communication\Plugin\ConfigurableBundleGui\ProductConcreteRelationConfigurableBundleTemplateSlotEditSubTabsProviderPlugin;
use Spryker\Zed\ProductListGui\Communication\Plugin\ConfigurableBundleGui\ProductConcreteRelationConfigurableBundleTemplateSlotEditTablesProviderPlugin;
use Spryker\Zed\ProductListGui\Communication\Plugin\ConfigurableBundleGui\ProductConcreteRelationCsvConfigurableBundleTemplateSlotEditFormFileUploadHandlerPlugin;
use Spryker\Zed\ProductListGui\Communication\Plugin\ConfigurableBundleGui\ProductListManagementConfigurableBundleTemplateSlotEditFormDataProviderExpanderPlugin;
use Spryker\Zed\ProductListGui\Communication\Plugin\ConfigurableBundleGui\ProductListManagementConfigurableBundleTemplateSlotEditFormExpanderPlugin;
use Spryker\Zed\ProductListGui\Communication\Plugin\ConfigurableBundleGui\ProductListManagementConfigurableBundleTemplateSlotEditTabsExpanderPlugin;
class ConfigurableBundleGuiDependencyProvider extends SprykerConfigurableBundleGuiDependencyProvider
{
/**
* @return \Spryker\Zed\ConfigurableBundleGuiExtension\Dependency\Plugin\ConfigurableBundleTemplateSlotEditTabsExpanderPluginInterface[]
*/
protected function getConfigurableBundleTemplateSlotEditTabsExpanderPlugins(): array
{
return [
new ProductListManagementConfigurableBundleTemplateSlotEditTabsExpanderPlugin(),
];
}
/**
* @return \Spryker\Zed\ConfigurableBundleGuiExtension\Dependency\Plugin\ConfigurableBundleTemplateSlotEditFormExpanderPluginInterface[]
*/
protected function getConfigurableBundleTemplateSlotEditFormExpanderPlugins(): array
{
return [
new ProductListManagementConfigurableBundleTemplateSlotEditFormExpanderPlugin(),
];
}
/**
* @return \Spryker\Zed\ConfigurableBundleGuiExtension\Dependency\Plugin\ConfigurableBundleTemplateSlotEditFormDataProviderExpanderPluginInterface[]
*/
protected function getConfigurableBundleTemplateSlotEditFormDataProviderExpanderPlugins(): array
{
return [
new ProductListManagementConfigurableBundleTemplateSlotEditFormDataProviderExpanderPlugin(),
];
}
/**
* @return \Spryker\Zed\ConfigurableBundleGuiExtension\Dependency\Plugin\ConfigurableBundleTemplateSlotEditFormFileUploadHandlerPluginInterface[]
*/
protected function getConfigurableBundleTemplateSlotEditFormFileUploadHandlerPlugins(): array
{
return [
new ProductConcreteRelationCsvConfigurableBundleTemplateSlotEditFormFileUploadHandlerPlugin(),
];
}
/**
* @return \Spryker\Zed\ConfigurableBundleGuiExtension\Dependency\Plugin\ConfigurableBundleTemplateSlotEditSubTabsProviderPluginInterface[]
*/
protected function getConfigurableBundleTemplateSlotEditSubTabsProviderPlugins(): array
{
return [
new ProductConcreteRelationConfigurableBundleTemplateSlotEditSubTabsProviderPlugin(),
];
}
/**
* @return \Spryker\Zed\ConfigurableBundleGuiExtension\Dependency\Plugin\ConfigurableBundleTemplateSlotEditTablesProviderPluginInterface[]
*/
protected function getConfigurableBundleTemplateSlotEditTablesProviderPlugins(): array
{
return [
new ProductConcreteRelationConfigurableBundleTemplateSlotEditTablesProviderPlugin(),
];
}
}
Make sure that on configurable bundle template slot edit page (http://zed.mysprykershop.com/configurable-bundle-gui/slot/edit?id-configurable-bundle-template-slot=1
):
- Assign Categories tab exists.
- Assign Products tab exists.
Register plugins for the ProductListGui module
PLUGIN | SPECIFICATION | PREREQUISITES | NAMESPACE |
---|---|---|---|
ConfigurableBundleTemplateListProductListTopButtonsExpanderPlugin | Expands buttons list with button leads to a Configurable Bundle Template list page. | None | Spryker\Zed\ConfigurableBundleGui\Communication\Plugin\ProductListGui |
ConfigurableBundleTemplateProductListUsedByTableExpanderPlugin | Expands table data with Configurable Bundle Templates and Slots which use Product List. | None | Spryker\Zed\ConfigurableBundleGui\Communication\Plugin\ProductListGui |
src/Pyz/Zed/ProductListGui/ProductListGuiDependencyProvider.php
<?php
namespace Pyz\Zed\ProductListGui;
use Spryker\Zed\ConfigurableBundleGui\Communication\Plugin\ProductListGui\ConfigurableBundleTemplateListProductListTopButtonsExpanderPlugin;
use Spryker\Zed\ConfigurableBundleGui\Communication\Plugin\ProductListGui\ConfigurableBundleTemplateProductListUsedByTableExpanderPlugin;
use Spryker\Zed\ProductListGui\ProductListGuiDependencyProvider as SprykerProductListGuiDependencyProvider;
class ProductListGuiDependencyProvider extends SprykerProductListGuiDependencyProvider
{
/**
* @return \Spryker\Zed\ProductListGuiExtension\Dependency\Plugin\ProductListTopButtonsExpanderPluginInterface[]
*/
protected function getProductListTopButtonsExpanderPlugins(): array
{
return [
new ConfigurableBundleTemplateListProductListTopButtonsExpanderPlugin(),
];
}
/**
* @return \Spryker\Zed\ProductListGuiExtension\Dependency\Plugin\ProductListUsedByTableExpanderPluginInterface[]
*/
protected function getProductListUsedByTableExpanderPlugins(): array
{
return [
new ConfigurableBundleTemplateProductListUsedByTableExpanderPlugin(),
];
}
}
Make sure that Configurable Bundle Templates button exists on Overview of Product lists (http://zed.mysprykershop.com/product-list-gui
) page.
Make sure that Used by table is populated by configurable bundle template slots on Edit Product List page (in cases of relationship).
9) Build Zed UI frontend
Run the following command to enable Javascript and CSS changes for Zed:
console frontend:zed:build
Install feature frontend
Prerequisites
Please overview and install the necessary features before beginning the integration step.
Feature | Version |
---|---|
Spryker Core | 202404.0 |
Cart | 202404.0 |
Product | 202404.0 |
Prices | 202404.0 |
1) Install the required modules
Install the required modules using Composer:
composer require spryker-feature/configurable-bundle: "^202404.0" --update-with-dependencies
Make sure the following modules have been installed:
MODULE | EXPECTED DIRECTORY |
---|---|
ConfigurableBundleWidget | spryker-shop/configurable-bundle-widget |
SalesConfigurableBundleWidget | spryker-shop/sales-configurable-bundle-widget |
2) Enable controllers
Router List
Register router plugins:
PROVIDER | NAMESPACE |
---|---|
ConfigurableBundleWidgetRouteProviderPlugin | SprykerShop\Yves\ConfigurableBundleWidget\Plugin\Router |
ConfigurableBundlePageRouteProviderPlugin | SprykerShop\Yves\ConfigurableBundlePage\Plugin\Router |
src/Pyz/Yves/Router/RouterDependencyProvider.php
<?php
namespace Pyz\Yves\Router;
use Spryker\Yves\Router\RouterDependencyProvider as SprykerRouterDependencyProvider;
use SprykerShop\Yves\ConfigurableBundlePage\Plugin\Router\ConfigurableBundlePageRouteProviderPlugin;
use SprykerShop\Yves\ConfigurableBundleWidget\Plugin\Router\ConfigurableBundleWidgetRouteProviderPlugin;
class RouterDependencyProvider extends SprykerRouterDependencyProvider
{
/**
* @return \Spryker\Yves\RouterExtension\Dependency\Plugin\RouteProviderPluginInterface[]
*/
protected function getRouteProvider(): array
{
return [
new ConfigurableBundleWidgetRouteProviderPlugin(),
new ConfigurableBundlePageRouteProviderPlugin(),
];
}
}
Verify the ConfigurableBundleWidgetRouteProviderPlugin
, make sure that you can change the quantity and remove the configurable bundle from the cart.
Verify the ConfigurableBundlePageRouteProviderPlugin
, make sure that you can navigate to /configurator/template-selection
page.
3) Set up widgets
Register the following plugins to enable widgets:
PLUGIN | SPECIFICATION | PREREQUISITES | NAMESPACE |
---|---|---|---|
QuoteConfiguredBundleWidget | Displays configured bundles on a cart page. | None | SprykerShop\Yves\ConfigurableBundleWidget\Widget |
OrderConfiguredBundleWidget | Displays configured bundles on the order details page. | None | SprykerShop\Yves\SalesConfigurableBundleWidget\Widget |
src/Pyz/Yves/ShopApplication/ShopApplicationDependencyProvider.php
<?php
namespace Pyz\Yves\ShopApplication;
use SprykerShop\Yves\ConfigurableBundleWidget\Widget\QuoteConfiguredBundleWidget;
use SprykerShop\Yves\SalesConfigurableBundleWidget\Widget\OrderConfiguredBundleWidget;
use SprykerShop\Yves\ShopApplication\ShopApplicationDependencyProvider as SprykerShopApplicationDependencyProvider;
class ShopApplicationDependencyProvider extends SprykerShopApplicationDependencyProvider
{
/**
* @return string[]
*/
protected function getGlobalWidgets(): array
{
return [
QuoteConfiguredBundleWidget::class,
OrderConfiguredBundleWidget::class,
];
}
}
Run the following command to enable Javascript and CSS changes:
console frontend:yves:build
Make sure the following widgets were registered:
MODULE | TEST |
---|---|
QuoteConfiguredBundleWidget | Go to the cart (http://mysprykershop.com/cart ) with a configured bundle, make sure that you see items grouped by the configured bundle. |
OrderConfiguredBundleWidget | Go to the order that was made from a cart with a configured bundle, make sure that you see items grouped by the configured bundle. |
4) Set up configuration
Add the following configuration to your project:
CONFIGURATION | SPECIFICATION | NAMESPACE |
---|---|---|
ConfigurableBundleWidgetConfig::isQuantityChangeable() | Used to display block with quantity input form. | Pyz\Yves\ConfigurableBundleWidget |
src/Pyz/Yves/ConfigurableBundleWidget/ConfigurableBundleWidgetConfig.php
<?php
namespace Pyz\Yves\ConfigurableBundleWidget;
use SprykerShop\Yves\ConfigurableBundleWidget\ConfigurableBundleWidgetConfig as SprykerShopConfigurableBundleWidgetConfig;
class ConfigurableBundleWidgetConfig extends SprykerShopConfigurableBundleWidgetConfig
{
/**
* @return bool
*/
public function isQuantityChangeable(): bool
{
return true;
}
}
Make sure that each configured bundle on the cart (http://mysprykershop.com/cart
) contains a block with quantity input.
Thank you!
For submitting the form