Skip to content

Create catalog promotions in your Sylius store. Allows you to easily setup rules to change prices on all your products

License

Notifications You must be signed in to change notification settings

Setono/SyliusCatalogPromotionPlugin

Repository files navigation

Sylius Catalog Promotion Plugin

Latest Version Latest Unstable Version Software License Build Status

Plugin for Sylius to define permanent or time-limited promotions for products and automatically update prices.

Screenshot showing catalog promotions admin page

Install

Add plugin to composer.json

composer require setono/sylius-catalog-promotion-plugin

Register plugin

<?php
# config/bundles.php

return [
    // ...
    Setono\JobStatusBundle\SetonoJobStatusBundle::class => ['all' => true],
    Setono\SyliusCatalogPromotionPlugin\SetonoSyliusCatalogPromotionPlugin::class => ['all' => true],
    Sylius\Bundle\GridBundle\SyliusGridBundle::class => ['all' => true],
    // ...
];

Note, that we MUST define SetonoSyliusCatalogPromotionPlugin BEFORE SyliusGridBundle. Otherwise you'll see exception like this:

You have requested a non-existent parameter "setono_sylius_catalog_promotion.model.promotion.class".  

Add config

# config/packages/setono_sylius_catalog_promotion.yaml
imports:
    - { resource: "@SetonoSyliusCatalogPromotionPlugin/Resources/config/app/config.yaml" }
    # Uncomment if you want to add some catalog promotion fixtures to default suite
    # - { resource: "@SetonoSyliusCatalogPromotionPlugin/Resources/config/app/fixtures.yaml" }

Add routing

# config/routes/setono_sylius_catalog_promotion.yaml
setono_sylius_catalog_promotion_admin:
    resource: "@SetonoSyliusCatalogPromotionPlugin/Resources/config/admin_routing.yaml"
    prefix: /admin

Extend core classes

Extend ChannelPricing

<?php

declare(strict_types=1);

namespace App\Entity\Channel;

use Doctrine\ORM\Mapping as ORM;
use Setono\SyliusCatalogPromotionPlugin\Model\ChannelPricingInterface as CatalogPromotionChannelPricingInterface;
use Setono\SyliusCatalogPromotionPlugin\Model\ChannelPricingTrait as CatalogPromotionChannelPricingTrait;
use Sylius\Component\Core\Model\ChannelPricing as BaseChannelPricing;

/**
 * @ORM\Table(name="sylius_channel_pricing")
 * @ORM\Entity()
 */
class ChannelPricing extends BaseChannelPricing implements CatalogPromotionChannelPricingInterface
{
    use CatalogPromotionChannelPricingTrait;
}

Extend ChannelPricingRepository

<?php

declare(strict_types=1);

namespace App\Repository;

use Setono\SyliusCatalogPromotionPlugin\Doctrine\ORM\ChannelPricingRepositoryTrait as CatalogPromotionChannelPricingRepositoryTrait;
use Setono\SyliusCatalogPromotionPlugin\Repository\ChannelPricingRepositoryInterface as CatalogPromotionChannelPricingRepositoryInterface;
use Sylius\Bundle\ResourceBundle\Doctrine\ORM\EntityRepository;

class ChannelPricingRepository extends EntityRepository implements CatalogPromotionChannelPricingRepositoryInterface
{
    use CatalogPromotionChannelPricingRepositoryTrait;
}

Extend ProductRepository

<?php

declare(strict_types=1);

namespace App\Repository;

use Setono\SyliusCatalogPromotionPlugin\Doctrine\ORM\ProductRepositoryTrait as CatalogPromotionProductRepositoryTrait;
use Setono\SyliusCatalogPromotionPlugin\Repository\ProductRepositoryInterface as CatalogPromotionProductRepositoryInterface;
use Sylius\Bundle\CoreBundle\Doctrine\ORM\ProductRepository as BaseProductRepository;

class ProductRepository extends BaseProductRepository implements CatalogPromotionProductRepositoryInterface
{
    use CatalogPromotionProductRepositoryTrait;
}

Extend ProductVariantRepository

<?php

declare(strict_types=1);

namespace App\Repository;

use Setono\SyliusCatalogPromotionPlugin\Doctrine\ORM\ProductVariantRepositoryTrait as CatalogPromotionProductVariantRepositoryTrait;
use Setono\SyliusCatalogPromotionPlugin\Repository\ProductVariantRepositoryInterface as CatalogPromotionProductVariantRepositoryInterface;
use Sylius\Bundle\CoreBundle\Doctrine\ORM\ProductVariantRepository as BaseProductVariantRepository;

class ProductVariantRepository extends BaseProductVariantRepository implements CatalogPromotionProductVariantRepositoryInterface
{
    use CatalogPromotionProductVariantRepositoryTrait;
}

Update config with extended classes

In your config/packages/_sylius.yaml file update the configured classes:

# config/packages/_sylius.yaml
sylius_core:
    resources:
        channel_pricing:
            classes:
                model: App\Entity\ChannelPricing
                repository: App\Repository\ChannelPricingRepository

sylius_product:
    resources:
        product:
            classes:
                repository: App\Repository\ProductRepository
        product_variant:
            classes:
                repository: App\Repository\ProductVariantRepository

Update your schema

Create a migration file:

$ php bin/console doctrine:migrations:diff

If you have existing discounted products you should append this line to the up method in the migration file:

<?php
namespace DoctrineMigrations;

use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;

final class Version20191028134956 extends AbstractMigration
{
    public function up(Schema $schema) : void
    {
        // The generated SQL will be here
        // ...
        
        // append this line
        $this->addSql('UPDATE sylius_channel_pricing SET manually_discounted = 1 WHERE original_price IS NOT NULL AND price != original_price');
    }

    public function down(Schema $schema) : void
    {
        // ...
    }
}

Execute migration file:

$ php bin/console doctrine:migrations:migrate

Install assets

bin/console sylius:install:assets

Configure CRON to run next command every minute

$ php bin/console setono:sylius-catalog-promotion:process