Issue with Price Sorting After Implementing Custom Discount Provider and Exclude Product Decorator in Price Rules
Forum rules
Always add your Aimeos and PHP version as well as your environment (Linux/Mac/Win)
Spam and unrelated posts will be removed immediately!
Always add your Aimeos and PHP version as well as your environment (Linux/Mac/Win)
Spam and unrelated posts will be removed immediately!
- Paulus-Ragnarr
- Posts: 16
- Joined: 15 Oct 2024, 07:02
Issue with Price Sorting After Implementing Custom Discount Provider and Exclude Product Decorator in Price Rules
Hi Aimeos,
I’ve implemented a custom price rule using a provider and catalog decorator. The Discount Provider applies a discount as an integer value, and the Exclude Product Decorator excludes certain products based on criteria such as product.codes, catalog.code, and products that already include a rebate in the current price. While the discount application works as expected, we’re experiencing an issue with price sorting. After applying the price rule, the sorting behavior is no longer consistent with the previous functionality.
Could you advise on how to address this sorting issue?
Here's the codes
//Discount Provider
//Exclude Product Decorator
// Jsonapi query
I’ve implemented a custom price rule using a provider and catalog decorator. The Discount Provider applies a discount as an integer value, and the Exclude Product Decorator excludes certain products based on criteria such as product.codes, catalog.code, and products that already include a rebate in the current price. While the discount application works as expected, we’re experiencing an issue with price sorting. After applying the price rule, the sorting behavior is no longer consistent with the previous functionality.
Could you advise on how to address this sorting issue?
Here's the codes
//Discount Provider
Code: Select all
<?php
namespace Aimeos\MShop\Rule\Provider\Catalog;
class Discount
extends \Aimeos\MShop\Rule\Provider\Base
implements \Aimeos\MShop\Rule\Provider\Catalog\Iface, \Aimeos\MShop\Rule\Provider\Factory\Iface
{
private array $beConfig = [
'discount' => [
'code' => 'discount',
'internalcode' => 'discount',
'label' => 'Percentage discount',
'type' => 'number',
'default' => '0',
'required' => true,
],
];
public function checkConfigBE( array $attributes ) : array
{
$errors = parent::checkConfigBE( $attributes );
return array_merge( $errors, $this->checkConfig( $this->beConfig, $attributes ) );
}
public function getConfigBE(): array
{
return array_replace( parent::getConfigBE(), $this->getConfigItems( $this->beConfig ) );
}
public function apply( \Aimeos\MShop\Product\Item\Iface $product ) : bool
{
$this->update( $product, (int) $this->getConfigValue( 'discount' ) );
return $this->isLast();
}
protected function update( \Aimeos\MShop\Product\Item\Iface $product, float $discount )
{
foreach ( $product->getRefItems( 'price' ) as $price )
{
$value = $price->getValue();
$diff = $value * $discount / 100;
$price->setValue( $value - $diff )->setRebate( $diff );
}
foreach ( $product->getRefItems( 'product' ) as $subproduct ) {
$this->update( $subproduct, $discount );
}
}
}
Code: Select all
<?php
namespace Aimeos\MShop\Rule\Provider\Catalog\Decorator;
use Illuminate\Support\Facades\Log;
class ExcludeProduct extends \Aimeos\MShop\Rule\Provider\Catalog\Decorator\Base implements \Aimeos\MShop\Rule\Provider\Catalog\Decorator\Iface
{
private array $codes;
private array $productCodes;
private string $excludeCatalog = 'soidukid,kawasaki,polaris,triumph,indianvoge,kinkekaardid';
private array $beConfig = [
'category.code' => [
'code' => 'category.code',
'internalcode' => 'category.code',
'label' => 'Except category codes',
'type' => 'string',
'default' => '',
'required' => true,
],
'product.code' => [
'code' => 'product.code',
'internalcode' => 'product.code',
'label' => 'Except product codes',
'default' => '',
'required' => false,
]
];
/**
* Initializes the rule instance
*
* @param \Aimeos\MShop\ContextIface $context Context object with required objects
* @param \Aimeos\MShop\Rule\Item\Iface $item Rule item object
* @param \Aimeos\MShop\Rule\Provider\Iface $provider Rule provider object
*/
public function __construct(
\Aimeos\MShop\ContextIface $context,
\Aimeos\MShop\Rule\Item\Iface $item,
\Aimeos\MShop\Rule\Provider\Iface $provider
) {
parent::__construct($context, $item, $provider);
$this->beConfig['category.code']['default'] = $this->excludeCatalog;
$this->codes = array_filter(explode(',', str_replace(' ', '', $this->getConfigValue('category.code', ''))));
$this->productCodes = array_filter(explode(',', str_replace(' ', '', $this->getConfigValue('product.code', ''))));
}
/**
* Checks the backend configuration attributes for validity.
*
* @param array $attributes Attributes added by the shop owner in the administraton interface
* @return array An array with the attribute keys as key and an error message as values for all attributes that are
* known by the provider but aren't valid resp. null for attributes whose values are OK
*/
public function checkConfigBE(array $attributes): array
{
$errors = parent::checkConfigBE($attributes);
return array_merge($errors, $this->checkConfig($this->beConfig, $attributes));
}
/**
* Returns the configuration attribute definitions of the provider to generate a list of available fields and
* rules for the value of each field in the administration interface.
*
* @return array List of attribute definitions implementing \Aimeos\Base\Critera\Attribute\Iface
*/
public function getConfigBE(): array
{
return array_merge(parent::getConfigBE(), $this->getConfigItems($this->beConfig));
}
/**
* Applies the rule to the given products
*
* @param \Aimeos\MShop\Product\Item\Iface $product Product the rule should be applied to
* @return bool True if rule is the last one, false to continue with further rules
*/
public function apply(\Aimeos\MShop\Product\Item\Iface $product): bool
{
if (in_array($product->getCode(), $this->productCodes) || $product->getConfigValue('is_vehicle') == 1) {
return false;
}
foreach ($product->getRefItems('price') as $priceItem) {
if ($priceItem->getRebate() > 0) {
return false;
}
}
foreach ($product->getRefItems('catalog') as $catItem) {
if (in_array($catItem->getCode(), $this->codes)) {
return false;
}
}
return $this->getProvider()->apply($product);
}
}
Code: Select all
http://localhost:8000/jsonapi/product?page%5Boffset%5D=0&page%5Blimit%5D=25&include=attribute,media,price,product,product/property,text,catalog,supplier,stock,tag,size&filter%5Bf_catid%5D=37&sort=-price
- Attachments
-
- Screenshot 2024-11-07 at 12.50.48 PM.png (164.55 KiB) Viewed 29497 times
-
- Screenshot 2024-11-07 at 12.44.54 PM.png (40.52 KiB) Viewed 29498 times
-
- Screenshot 2024-11-07 at 12.42.52 PM.png (203.71 KiB) Viewed 29498 times
Re: Issue with Price Sorting After Implementing Custom Discount Provider and Exclude Product Decorator in Price Rules
Short answer: You can't!
You are manipulating the prices after they have been sorted by the database. The only thing you can do is to resort the products by the new price in the catalog list template for that page but then, the prices on the next page can still be higher/lower than the prices on the current page.
You are manipulating the prices after they have been sorted by the database. The only thing you can do is to resort the products by the new price in the catalog list template for that page but then, the prices on the next page can still be higher/lower than the prices on the current page.
Professional support and custom implementation are available at Aimeos.com
If you like Aimeos, give us a star
If you like Aimeos, give us a star
- Paulus-Ragnarr
- Posts: 16
- Joined: 15 Oct 2024, 07:02
Re: Issue with Price Sorting After Implementing Custom Discount Provider and Exclude Product Decorator in Price Rules
Thank you for the reply.
Is there any other option for price sort to include discounted prices or for price rule functionality(discounts)?
This functionality is essential for us, as we need to apply discounts across all products without manually adjusting each product’s details. Our store has nearly 15,000 products with various discount specifications, and the price rule feature has been invaluable in managing these efficiently.
Thank you!
Update: We are considering implementing a custom price rule(discount) panel where an admin can create a discount that generates an additional price for the product with a "sale-price" type. We’re also exploring ways to add this "sale-price" to the index_price to enable sorting by discounted prices.
Is there any other option for price sort to include discounted prices or for price rule functionality(discounts)?
This functionality is essential for us, as we need to apply discounts across all products without manually adjusting each product’s details. Our store has nearly 15,000 products with various discount specifications, and the price rule feature has been invaluable in managing these efficiently.
Thank you!
Update: We are considering implementing a custom price rule(discount) panel where an admin can create a discount that generates an additional price for the product with a "sale-price" type. We’re also exploring ways to add this "sale-price" to the index_price to enable sorting by discounted prices.
Re: Issue with Price Sorting After Implementing Custom Discount Provider and Exclude Product Decorator in Price Rules
As long as you use dynamic price rules, sorting by price won't work as expected if the products are not all only in one category where you apply the same discount. Then, the relative order of the product prices is still fine.
Professional support and custom implementation are available at Aimeos.com
If you like Aimeos, give us a star
If you like Aimeos, give us a star