mirror of
https://github.com/Sylius/Sylius.git
synced 2026-07-14 17:10:53 +00:00
[Core] Channel pricings validation + cascade deletion
This commit is contained in:
parent
6691f5c2ac
commit
c5908d44d9
12 changed files with 201 additions and 10 deletions
40
app/migrations/Version20161123153400.php
Normal file
40
app/migrations/Version20161123153400.php
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
|
||||
namespace Sylius\Migrations;
|
||||
|
||||
use Doctrine\DBAL\Migrations\AbstractMigration;
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
|
||||
/**
|
||||
* Auto-generated Migration: Please modify to your needs!
|
||||
*/
|
||||
class Version20161123153400 extends AbstractMigration
|
||||
{
|
||||
/**
|
||||
* @param Schema $schema
|
||||
*/
|
||||
public function up(Schema $schema)
|
||||
{
|
||||
// this up() migration is auto-generated, please modify it to your needs
|
||||
$this->abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.');
|
||||
|
||||
$this->addSql('ALTER TABLE sylius_channel_pricing DROP FOREIGN KEY FK_7801820C72F5A1AA');
|
||||
$this->addSql('ALTER TABLE sylius_channel_pricing DROP FOREIGN KEY FK_7801820CA80EF684');
|
||||
$this->addSql('ALTER TABLE sylius_channel_pricing ADD CONSTRAINT FK_7801820C72F5A1AA FOREIGN KEY (channel_id) REFERENCES sylius_channel (id) ON DELETE CASCADE');
|
||||
$this->addSql('ALTER TABLE sylius_channel_pricing ADD CONSTRAINT FK_7801820CA80EF684 FOREIGN KEY (product_variant_id) REFERENCES sylius_product_variant (id) ON DELETE CASCADE');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Schema $schema
|
||||
*/
|
||||
public function down(Schema $schema)
|
||||
{
|
||||
// this down() migration is auto-generated, please modify it to your needs
|
||||
$this->abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.');
|
||||
|
||||
$this->addSql('ALTER TABLE sylius_channel_pricing DROP FOREIGN KEY FK_7801820CA80EF684');
|
||||
$this->addSql('ALTER TABLE sylius_channel_pricing DROP FOREIGN KEY FK_7801820C72F5A1AA');
|
||||
$this->addSql('ALTER TABLE sylius_channel_pricing ADD CONSTRAINT FK_7801820CA80EF684 FOREIGN KEY (product_variant_id) REFERENCES sylius_product_variant (id)');
|
||||
$this->addSql('ALTER TABLE sylius_channel_pricing ADD CONSTRAINT FK_7801820C72F5A1AA FOREIGN KEY (channel_id) REFERENCES sylius_channel (id)');
|
||||
}
|
||||
}
|
||||
|
|
@ -60,7 +60,7 @@ Feature: Products validation
|
|||
Then I should be notified that name is required
|
||||
And product with code "BOARD_DICE_BREWING" should not be added
|
||||
|
||||
@ui @todo
|
||||
@ui
|
||||
Scenario: Adding a new simple product without specifying its price for every channel
|
||||
Given the store operates on another channel named "Web-GB"
|
||||
When I want to create a new simple product
|
||||
|
|
@ -68,7 +68,7 @@ Feature: Products validation
|
|||
And I set its price to $10.00 for "United States" channel
|
||||
And I name it "Dice Brewing" in "English (United States)"
|
||||
And I try to add it
|
||||
Then I should be notified that price must be set for every channel
|
||||
Then I should be notified that price must be defined for every channel
|
||||
And product with code "BOARD_DICE_BREWING" should not be added
|
||||
|
||||
@ui
|
||||
|
|
|
|||
|
|
@ -9,13 +9,14 @@ Feature: Removing a product's price after channel deletion
|
|||
And the store has currency "GBP" with exchange rate 0.7
|
||||
And the store operates on a channel named "Web-US" in "USD" currency
|
||||
And the store operates on another channel named "Web-GB" in "GBP" currency
|
||||
And the store has a product "Dice Brewing" priced at "$10.00" for "Web-US" channel and "£5.00" for "Web-GB" channel
|
||||
And the store has a product "Dice Brewing" priced at "$10.00" in "Web-US" channel
|
||||
And this product is also priced at "£5.00" in "Web-GB" channel
|
||||
And I am logged in as an administrator
|
||||
|
||||
@ui @todo
|
||||
@ui
|
||||
Scenario: Removing a product's price after corresponding channel deletion
|
||||
When I delete channel "Web-GB"
|
||||
Then product "Dice Brewing" should have price "$10.00" for channel "Web-US"
|
||||
When channel "Web-GB" has been deleted
|
||||
Then product "Dice Brewing" should be priced at $10.00 for channel "Web-US"
|
||||
And this product should no longer have price for channel "Web=GB"
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -155,6 +155,14 @@ final class ChannelContext implements Context
|
|||
$this->changeChannelState($channel, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When channel :channel has been deleted
|
||||
*/
|
||||
public function iChannelHasBeenDeleted(ChannelInterface $channel)
|
||||
{
|
||||
$this->channelRepository->remove($channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Given /^(its) default tax zone is (zone "([^"]+)")$/
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
namespace Sylius\Behat\Context\Ui\Admin;
|
||||
|
||||
use Behat\Behat\Context\Context;
|
||||
use Behat\Mink\Exception\ElementNotFoundException;
|
||||
use Sylius\Behat\NotificationType;
|
||||
use Sylius\Behat\Page\Admin\Crud\CreatePageInterface;
|
||||
use Sylius\Behat\Page\Admin\Crud\UpdatePageInterface;
|
||||
|
|
@ -910,6 +911,14 @@ final class ManagingProductsContext implements Context
|
|||
$this->assertValidationMessage('code', 'Product code must be unique.');
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then I should be notified that price must be defined for every channel
|
||||
*/
|
||||
public function iShouldBeNotifiedThatPriceMustBeDefinedForEveryChannel()
|
||||
{
|
||||
$this->assertValidationMessage('channel_pricings', 'You must define price for every channel.');
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then they should have order like :firstProductName, :secondProductName and :thirdProductName
|
||||
*/
|
||||
|
|
@ -958,8 +967,8 @@ final class ManagingProductsContext implements Context
|
|||
}
|
||||
|
||||
/**
|
||||
* @Given /^(it|this product) should be priced at (?:€|£|\$)([^"]+) for channel "([^"]+)"$/
|
||||
* @Given /^(product "[^"]+") should be priced at (?:€|£|\$)([^"]+) for channel "([^"]+)"$/
|
||||
* @Then /^(it|this product) should be priced at (?:€|£|\$)([^"]+) for channel "([^"]+)"$/
|
||||
* @Then /^(product "[^"]+") should be priced at (?:€|£|\$)([^"]+) for channel "([^"]+)"$/
|
||||
*/
|
||||
public function itShouldBePricedAtForChannel(ProductInterface $product, $price, $channelName)
|
||||
{
|
||||
|
|
@ -971,6 +980,24 @@ final class ManagingProductsContext implements Context
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then /^(this product) should no longer have price for channel "([^"]+)"$/
|
||||
*/
|
||||
public function thisProductShouldNoLongerHavePriceForChannel(ProductInterface $product, $channelName)
|
||||
{
|
||||
$this->updateSimpleProductPage->open(['id' => $product->getId()]);
|
||||
|
||||
try {
|
||||
$this->updateSimpleProductPage->getPriceForChannel($channelName);
|
||||
} catch (ElementNotFoundException $exception) {
|
||||
return;
|
||||
}
|
||||
|
||||
throw new \Exception(
|
||||
sprintf('Product "%s" should not have price defined for channel "%s".', $product->getName(), $channelName)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $element
|
||||
* @param string $value
|
||||
|
|
|
|||
|
|
@ -226,6 +226,7 @@ class CreateSimpleProductPage extends BaseCreatePage implements CreateSimpleProd
|
|||
'attribute_value' => '.attribute .label:contains("%attribute%") ~ input',
|
||||
'attributes_choice' => '#sylius_product_attribute_choice',
|
||||
'calculator' => '#sylius_calculator_container',
|
||||
'channel_pricings' => '#sylius_product_variant_channelPricings',
|
||||
'code' => '#sylius_product_code',
|
||||
'form' => 'form[name="sylius_product"]',
|
||||
'images' => '#sylius_product_images',
|
||||
|
|
|
|||
|
|
@ -91,6 +91,7 @@ class ProductVariantTypeExtension extends AbstractTypeExtension
|
|||
'label' => 'sylius.form.variant.price',
|
||||
'allow_add' => false,
|
||||
'allow_delete' => false,
|
||||
'error_bubbling' => false,
|
||||
])
|
||||
->addEventSubscriber($this->channelPricingFormSubscriber)
|
||||
;
|
||||
|
|
|
|||
|
|
@ -24,10 +24,10 @@
|
|||
<field name="price" column="price" type="integer"/>
|
||||
|
||||
<many-to-one field="productVariant" target-entity="Sylius\Component\Product\Model\ProductVariantInterface" inversed-by="channelPricings">
|
||||
<join-column name="product_variant_id" referenced-column-name="id" nullable="false" />
|
||||
<join-column name="product_variant_id" referenced-column-name="id" nullable="false" on-delete="CASCADE" />
|
||||
</many-to-one>
|
||||
<many-to-one field="channel" target-entity="Sylius\Component\Channel\Model\ChannelInterface">
|
||||
<join-column name="channel_id" referenced-column-name="id" nullable="false" />
|
||||
<join-column name="channel_id" referenced-column-name="id" nullable="false" on-delete="CASCADE" />
|
||||
</many-to-one>
|
||||
</mapped-superclass>
|
||||
|
||||
|
|
|
|||
|
|
@ -33,5 +33,9 @@
|
|||
<argument type="service" id="sylius.availability_checker" />
|
||||
<tag name="validator.constraint_validator" alias="sylius_cart_item_availability" />
|
||||
</service>
|
||||
<service id="sylius.validator.has_all_prices_defined" class="Sylius\Bundle\CoreBundle\Validator\Constraints\HasAllPricesDefinedValidator">
|
||||
<argument type="service" id="sylius.repository.channel" />
|
||||
<tag name="validator.constraint_validator" alias="sylius_has_all_prices_defined" />
|
||||
</service>
|
||||
</services>
|
||||
</container>
|
||||
|
|
|
|||
|
|
@ -52,5 +52,8 @@
|
|||
<option name="groups">sylius</option>
|
||||
</constraint>
|
||||
</property>
|
||||
<constraint name="Sylius\Bundle\CoreBundle\Validator\Constraints\HasAllPricesDefined">
|
||||
<option name="groups">sylius</option>
|
||||
</constraint>
|
||||
</class>
|
||||
</constraint-mapping>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,49 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Sylius package.
|
||||
*
|
||||
* (c) Paweł Jędrzejewski
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Sylius\Bundle\CoreBundle\Validator\Constraints;
|
||||
|
||||
use Symfony\Component\Validator\Constraint;
|
||||
|
||||
/**
|
||||
* @author Mateusz Zalewski <mateusz.zalewski@lakion.com>
|
||||
*/
|
||||
final class HasAllPricesDefined extends Constraint
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $message = 'You must define price for every channel.';
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getMessage()
|
||||
{
|
||||
return $this->message;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function validatedBy()
|
||||
{
|
||||
return 'sylius_has_all_prices_defined';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getTargets()
|
||||
{
|
||||
return Constraint::CLASS_CONSTRAINT;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Sylius package.
|
||||
*
|
||||
* (c) Paweł Jędrzejewski
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Sylius\Bundle\CoreBundle\Validator\Constraints;
|
||||
|
||||
use Sylius\Component\Channel\Repository\ChannelRepositoryInterface;
|
||||
use Sylius\Component\Core\Model\ChannelPricingInterface;
|
||||
use Symfony\Component\Validator\Constraint;
|
||||
use Symfony\Component\Validator\ConstraintValidator;
|
||||
use Webmozart\Assert\Assert;
|
||||
|
||||
/**
|
||||
* @author Mateusz Zalewski <mateusz.zalewski@lakion.com>
|
||||
*/
|
||||
final class HasAllPricesDefinedValidator extends ConstraintValidator
|
||||
{
|
||||
/**
|
||||
* @var ChannelRepositoryInterface
|
||||
*/
|
||||
private $channelRepository;
|
||||
|
||||
/**
|
||||
* @param ChannelRepositoryInterface $channelRepository
|
||||
*/
|
||||
public function __construct(ChannelRepositoryInterface $channelRepository)
|
||||
{
|
||||
$this->channelRepository = $channelRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function validate($productVariant, Constraint $constraint)
|
||||
{
|
||||
Assert::isInstanceOf($constraint, HasAllPricesDefined::class);
|
||||
|
||||
$enabledChannels = $this->channelRepository->findBy(['enabled' => true]);
|
||||
|
||||
foreach ($enabledChannels as $channel) {
|
||||
/** @var ChannelPricingInterface $channelPricing */
|
||||
$channelPricing = $productVariant->getChannelPricingForChannel($channel);
|
||||
if (null === $channelPricing || null === $channelPricing->getPrice()) {
|
||||
$this->context->addViolationAt('channelPricings', $constraint->getMessage());
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue