PriceProduct module details: reference information
Edit on GitHubThis document describes technical details of the PriceProduct module that are valid since version 2 of the module.
Price dimension
Starting from version 2.0.0 of the PriceProduct module, Default Price Dimension was implemented inside the PriceProduct to save BC. All prices imported by the new PriceProductDataImport would be in the Default Price Dimension. See Prices per Merchant Relation to learn more about the price dimension.
PriceProductService
Starting from version 2.0.0 of the PriceProduct
module, we have added the Service layer with PriceProductService
. Its purpose is to select only one price from the list of prices available for the current customer, taking into account the provided filter, which could contain a selected Store, Currency, Price mode (gross or net), and Quote (with customer information inside).
The prices list can come from Yves (Storage) and Zed (DB).
- In case with Yves, the
PriceProductFilterTransfer
object must be created for filtering, which contains named values (store name, currency code, named price mode, named price type). - In case with Zed, the
PriceProductCriteriaTransfer
object must be created for filtering, which contains IDs as values (store ID, currency ID, and price type ID).
If you need to add additional fields to one of these objects, add it to another one (if you added QTY to filter, criteria must be updated). So that PriceProductFilterTransfer
could always be converted to PriceProductCriteriaTransfer
.
PriceProductService
has plugins with /Spryker/Service/PriceProductExtension/Dependency/Plugin/PriceProductFilterPluginInterface
which enables filtering price for price dimension.
This filter can be really simple and filter price only by price dimension name, but it can also bear some logic, such as finding the minimum price from a price dimension.
After that, the list of prices passed to service will be decreased to the list of filtered prices, which fits the Filter object only and filters plugins logic.
Then /Spryker/Service/PriceProduct/FilterStrategy/SinglePriceProductFilterStrategyInterface
is applied for filtered prices to find only a single price (at the moment, there is only one built-in strategy SinglePriceProductFilterMinStrategy
which finds MIN price).
There is Quote in a filter/criteria
without items since this is additional information about the environment from where prices are requested.
That filter/criteria
is a flat object, so we filter only by its properties; however, plugins can use additional information (for example, Quote) for filtering.
Using the price dimensions
The PriceProduct
module has a set of plugins necessary for work with the price dimensions. All new plugin interfaces are now in the new module PriceProductExtension
. They are as follows:
Zed
PriceDimensionAbstractSaverPluginInterface
— saves price for abstract product in the DB for the selected price dimension (based onPriceProductTransfer->getPriceDimension())
PriceDimensionConcreteSaverPluginInterface
— saves price for concrete product in the DB for the selected price dimension (based onPriceProductTransfer->getPriceDimension())
PriceDimensionQueryCriteriaPluginInterface
— is used for expandingPriceProductStoreQuery
using the new transfer objectQueryCriteriaTransfer
.
Based on PriceProductCriteria
, you can build your own QueryCriteria
to get prices using joins—all prices can be selected from needed price dimensions using only one SQL query. See the DB scheme:
“Orphaned records”
According to the DB schema, the spy_price_product_store
table is the common storage for prices from different dimensions. If some price is the same for several dimensions, it will be stored as a single record. When a price is changed in one dimension, and there is no identical price in spy_price_product_store
, the price will be stored as a new record in this table. This is done to avoid overriding prices in other dimensions. After some time, this table will have so-called “orphaned records” (any price dimension does not have a reference to these prices). To automatically remove them, you can use src/Pyz/Zed/PriceProduct/PriceProductConfig.php
:
namespace Pyz/Zed/PriceProduct;
use Spryker/Zed/PriceProduct/PriceProductConfig as SprykerPriceProductConfig;
class PriceProductConfig extends SprykerPriceProductConfig
{
/**
* Perform orphan prices removing automatically.
*/
protected const IS_DELETE_ORPHAN_STORE_PRICES_ON_SAVE_ENABLED = true;
}
Alternatively, automatic removal of “orphaned records” can be enabled by using AclEntityOrphanPriceProductStoreRemovalVoterPlugin
in src/Pyz/Zed/PriceProduct/PriceProductDependencyProvider.php
:
namespace Pyz\Zed\PriceProduct;
use Spryker\Zed\AclEntity\Communication\Plugin\PriceProduct\AclEntityOrphanPriceProductStoreRemovalVoterPlugin;
use Spryker\Zed\PriceProduct\PriceProductDependencyProvider as SprykerPriceProductDependencyProvider;
class PriceProductDependencyProvider extends SprykerPriceProductDependencyProvider
{
protected function getOrphanPriceProductStoreRemovalVoterPlugins(): array
{
return [
new AclEntityOrphanPriceProductStoreRemovalVoterPlugin(),
];
}
}
AclEntityOrphanPriceProductStoreRemovalVoterPlugin
enables the removal of “orphaned” records in the spy_price_product_store
table, except for the case when prices are edited in the Merchant Portal UI.
In the latter case, removal is only possible by running price-product-store:optimize
command (see below).
Note, that this plugin can’t be used together with config constant IS_DELETE_ORPHAN_STORE_PRICES_ON_SAVE_ENABLED
described above, either of the two must be used only, with the plugin being preferred, since the config constant is deprecated and will be removed in the next major release of the PriceProduct
module.
Another option is to run console price-product-store:optimize
from time to time when needed.
Service
PriceProductFilterPluginInterface
— filters array of prices based onPriceProductFilterTransfer
.PriceProductDimensionExpanderStrategyPluginInterface
— expandsPriceProductDimension
transfer basing on some properties of this transfer (likeidPriceProductDefault
).
Reading prices from Storage is implemented in the PriceProductStorage
module, plugins for reading prices reside in the PriceProductStorageExtension
module (/Spryker/Client/PriceProductStorageExtension/Dependency/Plugin/PriceProductStoragePriceDimensionPluginInterface
) which has two methods for reading prices from Storage: findProductConcretePrices($id)
and findProductAbstractPrices($id)
Prices for price dimension inside Storage are supposed to be stored as a separate key-value for each product, abstract and concrete. For example, can check kv:price_product_abstract:X
(X = ID of product).
All plugins can be added on the project level in:
PriceProductDependencyProvider
for the Zed and Service layers.PriceProductStorageDependencyProvider
for the Client layer.
Thank you!
For submitting the form