Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Order] allow passing custom-attributes from price rules to order-item #2555

Merged
merged 13 commits into from
Mar 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions features/domain/cart/not_discountable_action.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
@domain @cart
Feature: Adding a not discountable attribute to the cart item
In order to allow custom order-item attributes based on pricing rules
we add a not-discountable attribute to the cart item

Background:
Given the site operates on a store in "Austria"
And the site has a currency "Euro" with iso "EUR"
And I am in country "Austria"
And the site has two categories "Shoes" and "Coats"
And the site has a product "Shoe" priced at 10000
And it is in category "Shoes"

Scenario: Adding no not-discountable price rule
Given I add the product "Shoe" to my cart
Then the cart item with product should not have a custom attribute named "not_discountable"

Scenario: Adding a not-discountable price rule
Given adding a product price rule named "not-discountable"
And the price rule is active
And the price rule has a action not-discountable
And I add the product "Shoe" to my cart
Then the cart item with product should have a custom attribute named "not_discountable"
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
@domain @cart
Feature: Adding a new cart rule
In order to give the customer discounts
based on the cart, we add a new rule

Background:
Given the site operates on a store in "Austria"
And the site has a currency "Euro" with iso "EUR"
And I am in country "Austria"
And the site has a product "Shoe" priced at 10000
And adding a product price rule named "not-discountable"
And the price rule is active
And the price rule has a action not-discountable
And I add the product "Shoe" to my cart

Scenario: Add a new discount rule with 20 percent discount for all products
Given adding a cart price rule named "discount"
And the cart rule is active
And the cart rule is a voucher rule with code "asdf"
And the cart rule has a action discount with 20 in currency "EUR" off
And I apply the voucher code "asdf" to my cart
Then the cart discount should be "0" including tax
Then the cart total should be "10000" including tax

Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
@domain @cart
Feature: Adding a new cart rule
In order to give the customer discounts
based on the cart, we add a new rule

Background:
Given the site operates on a store in "Austria"
And the site has a currency "Euro" with iso "EUR"
And I am in country "Austria"
And the site has two categories "Shoes" and "Coats"
And the site has a product "Shoe" priced at 10000
And it is in category "Shoes"
And I add the product "Shoe" to my cart
And adding a product price rule named "not-discountable"
And the price rule is active
And the price rule has a action not-discountable

Scenario: Add a new discount rule with 20 percent discount for all products
Given adding a cart price rule named "discount"
And the cart rule is active
And the cart rule is a voucher rule with code "asdf"
And the cart rule has a action discount-percent with 10% discount
And I apply the voucher code "asdf" to my cart
Then the cart discount should be "0" including tax
Then the cart total should be "10000" including tax
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
@domain @cart
Feature: Adding a new cart rule
In order to give the customer discounts
based on the cart, we add a new rule

Background:
Given the site operates on a store in "Austria"
And the site has a currency "Euro" with iso "EUR"
And I am in country "Austria"
And the site has two categories "Shoes" and "Coats"
And the site has a product "Shoe" priced at 10000
And it is in category "Shoes"
And adding a product specific price rule to product "Shoe" named "not-discountable"
And the specific price rule is active
And the specific price rule has a action not-discountable
And the site has a product "Jacket" priced at 40000
And it is in category "Coats"
And I add the product "Shoe" to my cart
And I add the product "Jacket" to my cart

Scenario: Add a new discount rule with 20 percent discount for all products
Given adding a cart price rule named "discount"
And the cart rule is active
And the cart rule is a voucher rule with code "asdf"
And the cart rule has a action discount-percent with 10% discount
And I apply the voucher code "asdf" to my cart
Then the cart discount should be "-5000" including tax
Then the cart total should be "45000" including tax
36 changes: 36 additions & 0 deletions src/CoreShop/Behat/Context/Domain/CartContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -942,6 +942,42 @@ public function theCartItemWithProductShouldHaveAConvertedRetalWithoutTax(Produc
);
}

/**
* @Then /^the cart item with (product) should have a custom attribute named "([^"]+)"$/
* @Then /^the cart item with (product "[^"]+") should have a custom attribute named "([^"]+)"$/
*/
public function theCartItemWithProductShouldHaveACustomAttributeNamed(ProductInterface $product, string $attributeName): void
{
$cart = $this->cartContext->getCart();

/**
* @var OrderItemInterface $cartItem
*/
$cartItem = $this->findCartItemByProduct($cart, $product);

Assert::notNull(
$cartItem->findAttribute($attributeName),
);
}

/**
* @Then /^the cart item with (product) should not have a custom attribute named "([^"]+)"$/
* @Then /^the cart item with (product "[^"]+") should not have a custom attribute named "([^"]+)"$/
*/
public function theCartItemWithProductShouldNotHaveACustomAttributeNamed(ProductInterface $product, string $attributeName): void
{
$cart = $this->cartContext->getCart();

/**
* @var OrderItemInterface $cartItem
*/
$cartItem = $this->findCartItemByProduct($cart, $product);

Assert::null(
$cartItem->findAttribute($attributeName),
);
}

/**
* @Then /^the cart converted shipping should be "([^"]+)" excluding tax$/
*/
Expand Down
9 changes: 9 additions & 0 deletions src/CoreShop/Behat/Context/Setup/ProductPriceRuleContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,15 @@ public function theProductPriceRuleHasAPrice(ProductPriceRuleInterface $rule, $p
]));
}

/**
* @Given /^the (price rule "[^"]+") has a action not-discountable$/
* @Given /^the (price rule) has a action not-discountable$/
*/
public function theProductPriceRuleHasAActionNotDiscountable(ProductPriceRuleInterface $rule): void
{
$this->addAction($rule, $this->createActionWithForm('notDiscountableCustomAttributes'));
}

/**
* @Given /^the (price rule "[^"]+") has a condition quantity with min (\d+) and max (\d+)$/
* @Given /^the (price rule) has a condition quantity with min (\d+) and max (\d+)$/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,15 @@ public function theProductSpecificPriceRuleHasAPriceAction(ProductSpecificPriceR
]));
}

/**
* @Given /^the (specific price rule "[^"]+") has a action not-discountable$/
* @Given /^the (specific price rule) has a action not-discountable$/
*/
public function theProductSpecificPriceRuleHasANotDiscountableAction(ProductSpecificPriceRuleInterface $rule): void
{
$this->addAction($rule, $this->createActionWithForm('notDiscountableCustomAttributes'));
}

/**
* @Given /^the (specific price rule "[^"]+") has a condition nested with operator "([^"]+)" for (store "[^"]+") and (store "[^"]+")$/
* @Given /^the (specific price rule) has a condition nested with operator "([^"]+)" for (store "[^"]+") and (store "[^"]+")$/
Expand Down
2 changes: 2 additions & 0 deletions src/CoreShop/Behat/Resources/config/suites/domain/cart.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ default:
- coreshop.behat.context.transform.customer_group
- coreshop.behat.context.transform.zone
- coreshop.behat.context.transform.shipping
- coreshop.behat.context.transform.product_price_rule
- coreshop.behat.context.transform.product_specific_price_rule

- coreshop.behat.context.setup.tax_rate
Expand All @@ -40,6 +41,7 @@ default:
- coreshop.behat.context.setup.cart_price_rule_voucher_code
- coreshop.behat.context.setup.zone
- coreshop.behat.context.setup.shipping
- coreshop.behat.context.setup.product_price_rule
- coreshop.behat.context.setup.product_specific_price_rule
- coreshop.behat.context.setup.exchange_rate

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?php

declare(strict_types=1);

/*
* CoreShop
*
* This source file is available under two different licenses:
* - GNU General Public License version 3 (GPLv3)
* - CoreShop Commercial License (CCL)
* Full copyright and license information is available in
* LICENSE.md which is distributed with this source code.
*
* @copyright Copyright (c) CoreShop GmbH (https://www.coreshop.org)
* @license https://www.coreshop.org/license GPLv3 and CCL
*
*/

namespace CoreShop\Bundle\CoreBundle\Form\Extension;

use CoreShop\Bundle\OrderBundle\Form\Type\QuantityType;
use CoreShop\Component\Product\Model\ProductUnitDefinitionInterface;
use Symfony\Component\Form\AbstractTypeExtension;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\OptionsResolver\OptionsResolver;

final class QuantityTypeExtension extends AbstractTypeExtension
{
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'unit_definition' => null,
'attr' => [
'min' => 0,
'step' => 1,
'data-cs-unit-precision' => 0,
'autocomplete' => 'off',
],
]);

$resolver->setAllowedTypes('html5', 'bool');
}

public function buildView(FormView $view, FormInterface $form, array $options): void
{
if ($options['unit_definition'] instanceof ProductUnitDefinitionInterface) {
$precision = $options['unit_definition']->getPrecision();
$view->vars['attr']['data-cs-unit-precision'] = $precision;

if ($precision > 0) {
$view->vars['attr']['step'] = sprintf('0.%s1', str_repeat('0', $precision - 1));
}
}
}


public static function getExtendedTypes(): iterable
{
return [QuantityType::class];
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<?php

declare(strict_types=1);

namespace CoreShop\Bundle\CoreBundle\Migrations;

use CoreShop\Component\Pimcore\DataObject\ClassUpdate;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerAwareTrait;

final class Version20240218161440 extends AbstractMigration implements ContainerAwareInterface
{
use ContainerAwareTrait;

public function getDescription(): string
{
return '';
}

public function up(Schema $schema): void
{
$classUpdater = new ClassUpdate(
$this->container->getParameter('coreshop.model.order_item.pimcore_class_name'),
);

if ($classUpdater->hasField('attributes')) {
return;
}

$attributesField = [
'name' => 'attributes',
'title' => 'coreshop.order.attributes',
'tooltip' => '',
'mandatory' => false,
'noteditable' => false,
'index' => false,
'locked' => false,
'style' => '',
'permissions' => null,
'fieldtype' => 'fieldcollections',
'relationType' => false,
'invisible' => false,
'visibleGridView' => false,
'visibleSearch' => false,
'allowedTypes' => [
'CoreShopOrderItemAttribute',
],
'lazyLoading' => true,
'maxItems' => null,
'disallowAddRemove' => false,
'disallowReorder' => false,
'collapsed' => false,
'collapsible' => false,
'border' => false,
'datatype' => 'data',
];

$classUpdater->insertFieldAfter('priceRuleItems', $attributesField);
$classUpdater->save();
}

public function down(Schema $schema): void
{
// this down() migration is auto-generated, please modify it to your needs

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,4 @@ services:

CoreShop\Bundle\CoreBundle\Security\AccessVoter:
tags:
- { name: security.voter }
- { name: security.voter }
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ services:
tags:
- { name: form.type_extension, extended_type: CoreShop\Bundle\OrderBundle\Form\Type\CartCreationType }

CoreShop\Bundle\CoreBundle\Form\Extension\QuantityTypeExtension:
tags:
- { name: form.type_extension, extended_type: CoreShop\Bundle\OrderBundle\Form\Type\QuantityType }

CoreShop\Bundle\CoreBundle\Form\Extension\CartCreationCartItemTypeExtension:
arguments:
- '@coreshop.repository.stack.product'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,3 +87,10 @@ services:
- '@CoreShop\Component\Product\Calculator\ProductPriceCalculatorInterface'
tags:
- { name: coreshop.order.purchasable.discount_price_calculator, type: product, priority: 20 }

CoreShop\Component\Core\Order\Calculator\PurchasableProductCustomAttributesCalculator:
arguments:
- '@CoreShop\Component\Product\Calculator\ProductCustomAttributeCalculatorInterface'
- '@coreshop.factory.order_item_attribute'
tags:
- { name: coreshop.order.purchasable.custom_attributes_calculator, type: product, priority: 20 }
Loading