diff --git a/app/migrations/Version20170913125128.php b/app/migrations/Version20170913125128.php
new file mode 100644
index 00000000000..8ddd520d375
--- /dev/null
+++ b/app/migrations/Version20170913125128.php
@@ -0,0 +1,55 @@
+abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.');
+
+ $this->addSql('ALTER TABLE sylius_order_item ADD product_name VARCHAR(255), ADD variant_name VARCHAR(255)');
+
+ $this->addSql('
+ UPDATE sylius_order_item
+ INNER JOIN sylius_order ON sylius_order_item.order_id = sylius_order.id
+ INNER JOIN sylius_product_variant ON sylius_order_item.variant_id = sylius_product_variant.id
+ INNER JOIN sylius_product ON sylius_product_variant.product_id = sylius_product.id
+ INNER JOIN sylius_product_translation ON sylius_product_translation.translatable_id = sylius_product.id
+ SET sylius_order_item.product_name = sylius_product_translation.name
+ WHERE sylius_product_translation.locale = sylius_order.locale_code
+
+ ');
+ $this->addSql('
+ UPDATE sylius_order_item
+ INNER JOIN sylius_order ON sylius_order_item.order_id = sylius_order.id
+ INNER JOIN sylius_product_variant ON sylius_order_item.variant_id = sylius_product_variant.id
+ INNER JOIN sylius_product_variant_translation ON sylius_product_variant_translation.translatable_id = sylius_product_variant.id
+ SET sylius_order_item.variant_name = sylius_product_variant_translation.name
+ WHERE sylius_product_variant_translation.locale = sylius_order.locale_code
+ ');
+
+ $this->addSql('ALTER TABLE sylius_order_item CHANGE product_name product_name VARCHAR(255) DEFAULT NULL, CHANGE variant_name variant_name VARCHAR(255) DEFAULT NULL');
+ }
+
+ /**
+ * @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_order_item DROP product_name, DROP variant_name');
+ }
+}
diff --git a/features/account/customer_account/viewing_orders_history/viewing_order_items_with_proper_names.feature b/features/account/customer_account/viewing_orders_history/viewing_order_items_with_proper_names.feature
new file mode 100644
index 00000000000..4674e441688
--- /dev/null
+++ b/features/account/customer_account/viewing_orders_history/viewing_order_items_with_proper_names.feature
@@ -0,0 +1,26 @@
+@customer_account
+Feature: Viewing order items with proper names
+ In order to check some details of my placed order
+ As an Customer
+ I want to be able to view items with proper names of my placed order
+
+ Background:
+ Given the store operates on a single channel in "United States"
+ And the store has a product "Angel T-Shirt" priced at "$39.00"
+ And the store has a product "Angel Mug" priced at "$19.00"
+ And the store ships everywhere for free
+ And the store allows paying with "Cash on Delivery"
+ And I am a logged in customer
+ And I placed an order "#00000666"
+ And I bought an "Angel T-Shirt" and an "Angel Mug"
+ And I addressed it to "Lucifer Morningstar", "Seaside Fwy", "90802" "Los Angeles" in the "United States" with identical billing address
+ And I chose "Free" shipping method with "Cash on Delivery" payment
+
+ @ui
+ Scenario: Viewing basic information about an order
+ Given the product "Angel T-Shirt" was renamed to "Devil Cardigan"
+ And the product "Angel Mug" was renamed to "Devil Glass"
+ When I view the summary of the order "#00000666"
+ And I should see 2 items in the list
+ And the product named "Angel T-Shirt" should be in the items list
+ And the product named "Angel Mug" should be in the items list
diff --git a/features/order/managing_orders/seeing_order_items_with_proper_names.feature b/features/order/managing_orders/seeing_order_items_with_proper_names.feature
new file mode 100644
index 00000000000..87ca755e8fc
--- /dev/null
+++ b/features/order/managing_orders/seeing_order_items_with_proper_names.feature
@@ -0,0 +1,27 @@
+@managing_orders
+Feature: Seeing order items with proper names
+ In order to see ordered products with proper names
+ As an Administrator
+ I want to be able to list items
+
+ Background:
+ Given the store operates on a single channel in "United States"
+ And the store has a product "Angel T-Shirt" priced at "$39.00"
+ And the store has a product "Angel Mug" priced at "$19.00"
+ And the store ships everywhere for free
+ And the store allows paying with "Cash on Delivery"
+ And there is a customer "lucy@teamlucifer.com" that placed an order "#00000666"
+ And the customer bought an "Angel T-Shirt" and an "Angel Mug"
+ And the customer chose "Free" shipping method to "United States" with "Cash on Delivery" payment
+ And I am logged in as an administrator
+
+ @ui
+ Scenario: Seeing order items with proper names
+ Given the product "Angel T-Shirt" was renamed to "Devil Cardigan"
+ And the product "Angel Mug" was renamed to "Devil Glass"
+ When I view the summary of the order "#00000666"
+ Then it should have 2 items
+ And the product named "Angel T-Shirt" should be in the items list
+ And the product named "Angel Mug" should be in the items list
+ And the order's items total should be "$58.00"
+ And the order's total should be "$58.00"
diff --git a/src/Sylius/Behat/Context/Setup/ProductContext.php b/src/Sylius/Behat/Context/Setup/ProductContext.php
index 971dce110bd..b7d9fb378c4 100644
--- a/src/Sylius/Behat/Context/Setup/ProductContext.php
+++ b/src/Sylius/Behat/Context/Setup/ProductContext.php
@@ -782,6 +782,16 @@ public function thisProductHasBeenDisabled(ProductInterface $product)
$this->objectManager->flush();
}
+ /**
+ * @Given the product :product was renamed to :productName
+ */
+ public function theProductWasRenamedTo(ProductInterface $product, string $productName): void
+ {
+ $product->setName($productName);
+
+ $this->objectManager->flush();
+ }
+
/**
* @param string $price
*
diff --git a/src/Sylius/Behat/Page/Admin/Order/ShowPage.php b/src/Sylius/Behat/Page/Admin/Order/ShowPage.php
index 32497cf166c..a01159ab2ab 100644
--- a/src/Sylius/Behat/Page/Admin/Order/ShowPage.php
+++ b/src/Sylius/Behat/Page/Admin/Order/ShowPage.php
@@ -145,15 +145,24 @@ public function countItems()
/**
* {@inheritdoc}
*/
- public function isProductInTheList($productName)
+ public function isProductInTheList(string $productName): bool
{
try {
+ $table = $this->getElement('table');
$rows = $this->tableAccessor->getRowsWithFields(
- $this->getElement('table'),
+ $table,
['item' => $productName]
);
- return 1 === count($rows);
+ foreach ($rows as $row) {
+ $field = $this->tableAccessor->getFieldFromRow($table, $row, 'item');
+ $name = $field->find('css', '.sylius-product-name');
+ if (null !== $name && $name->getText() === $productName) {
+ return true;
+ }
+ }
+
+ return false;
} catch (\InvalidArgumentException $exception) {
return false;
}
diff --git a/src/Sylius/Behat/Page/Admin/Order/ShowPageInterface.php b/src/Sylius/Behat/Page/Admin/Order/ShowPageInterface.php
index ff05f775508..cf567f735f8 100644
--- a/src/Sylius/Behat/Page/Admin/Order/ShowPageInterface.php
+++ b/src/Sylius/Behat/Page/Admin/Order/ShowPageInterface.php
@@ -103,7 +103,7 @@ public function countItems();
*
* @return bool
*/
- public function isProductInTheList($productName);
+ public function isProductInTheList(string $productName): bool;
/**
* @return string
diff --git a/src/Sylius/Behat/Page/Shop/Account/Order/ShowPage.php b/src/Sylius/Behat/Page/Shop/Account/Order/ShowPage.php
index 3b0be8d0c94..a3e844460e2 100644
--- a/src/Sylius/Behat/Page/Shop/Account/Order/ShowPage.php
+++ b/src/Sylius/Behat/Page/Shop/Account/Order/ShowPage.php
@@ -122,15 +122,24 @@ public function getPaymentPrice()
/**
* {@inheritdoc}
*/
- public function isProductInTheList($name)
+ public function isProductInTheList(string $productName): bool
{
try {
+ $table = $this->getElement('order_items');
$rows = $this->tableAccessor->getRowsWithFields(
- $this->getElement('order_items'),
- ['item' => $name]
+ $table,
+ ['item' => $productName]
);
- return 1 === count($rows);
+ foreach ($rows as $row) {
+ $field = $this->tableAccessor->getFieldFromRow($table, $row, 'item');
+ $name = $field->find('css', '.sylius-product-name');
+ if (null !== $name && $name->getText() === $productName) {
+ return true;
+ }
+ }
+
+ return false;
} catch (\InvalidArgumentException $exception) {
return false;
}
diff --git a/src/Sylius/Behat/Page/Shop/Account/Order/ShowPageInterface.php b/src/Sylius/Behat/Page/Shop/Account/Order/ShowPageInterface.php
index 9fea45da276..21caeec874e 100644
--- a/src/Sylius/Behat/Page/Shop/Account/Order/ShowPageInterface.php
+++ b/src/Sylius/Behat/Page/Shop/Account/Order/ShowPageInterface.php
@@ -65,11 +65,11 @@ public function countItems();
public function getPaymentPrice();
/**
- * @param string $name
+ * @param string $productName
*
* @return bool
*/
- public function isProductInTheList($name);
+ public function isProductInTheList(string $productName): bool;
/**
* @return string
diff --git a/src/Sylius/Bundle/AdminBundle/Resources/views/Product/_info.html.twig b/src/Sylius/Bundle/AdminBundle/Resources/views/Product/_info.html.twig
index 8a710b2519a..41c8c0f5f82 100644
--- a/src/Sylius/Bundle/AdminBundle/Resources/views/Product/_info.html.twig
+++ b/src/Sylius/Bundle/AdminBundle/Resources/views/Product/_info.html.twig
@@ -1,9 +1,7 @@
-{% set product = variant.product %}
-
-{% elseif variant.name is not null %}
+{% elseif item.variantName is not null %}
- {{ variant.name }}
+ {{ item.variantName }}
{% endif %}
diff --git a/src/Sylius/Bundle/CoreBundle/Resources/config/app/state_machine/sylius_order.yml b/src/Sylius/Bundle/CoreBundle/Resources/config/app/state_machine/sylius_order.yml
index 1bff13d5d85..8b5e7ebddb3 100644
--- a/src/Sylius/Bundle/CoreBundle/Resources/config/app/state_machine/sylius_order.yml
+++ b/src/Sylius/Bundle/CoreBundle/Resources/config/app/state_machine/sylius_order.yml
@@ -58,6 +58,10 @@ winzou_state_machine:
on: ["create"]
do: ["@sylius.customer_order_addresses_saver", "saveAddresses"]
args: ["object"]
+ sylius_set_order_immutable_names:
+ on: ["create"]
+ do: ["@sylius.order_item_names_setter", "__invoke"]
+ args: ["object"]
sylius_cancel_payment:
on: ["cancel"]
do: ["@sm.callback.cascade_transition", "apply"]
diff --git a/src/Sylius/Bundle/CoreBundle/Resources/config/doctrine/model/OrderItem.orm.xml b/src/Sylius/Bundle/CoreBundle/Resources/config/doctrine/model/OrderItem.orm.xml
index 8b60d7e6bb8..72ab68cdfe8 100644
--- a/src/Sylius/Bundle/CoreBundle/Resources/config/doctrine/model/OrderItem.orm.xml
+++ b/src/Sylius/Bundle/CoreBundle/Resources/config/doctrine/model/OrderItem.orm.xml
@@ -17,6 +17,9 @@
http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
+
+
+
diff --git a/src/Sylius/Bundle/CoreBundle/Resources/config/services.xml b/src/Sylius/Bundle/CoreBundle/Resources/config/services.xml
index bfe59b31e2c..8546b173d38 100644
--- a/src/Sylius/Bundle/CoreBundle/Resources/config/services.xml
+++ b/src/Sylius/Bundle/CoreBundle/Resources/config/services.xml
@@ -164,5 +164,7 @@
+
+
diff --git a/src/Sylius/Bundle/ShopBundle/Resources/views/Product/_info.html.twig b/src/Sylius/Bundle/ShopBundle/Resources/views/Product/_info.html.twig
index 8cebac94a90..f7024eef4b6 100644
--- a/src/Sylius/Bundle/ShopBundle/Resources/views/Product/_info.html.twig
+++ b/src/Sylius/Bundle/ShopBundle/Resources/views/Product/_info.html.twig
@@ -3,7 +3,7 @@
-{% elseif variant.name is not null %}
+{% elseif item.variantName is not null %}
- {{ variant.name }}
+ {{ item.variantName }}
{% endif %}
diff --git a/src/Sylius/Component/Core/Model/OrderItem.php b/src/Sylius/Component/Core/Model/OrderItem.php
index 3e130e30317..15d1b66458b 100644
--- a/src/Sylius/Component/Core/Model/OrderItem.php
+++ b/src/Sylius/Component/Core/Model/OrderItem.php
@@ -23,9 +23,35 @@ class OrderItem extends BaseOrderItem implements OrderItemInterface
*/
protected $variant;
+ /**
+ * @var string
+ */
+ protected $productName;
+
+ /**
+ * @var string
+ */
+ protected $variantName;
+
/**
* {@inheritdoc}
*/
+ public function getVariant(): ?ProductVariantInterface
+ {
+ return $this->variant;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setVariant(?ProductVariantInterface $variant): void
+ {
+ $this->variant = $variant;
+ }
+
+ /**
+ * @return ProductInterface|null
+ */
public function getProduct(): ?ProductInterface
{
return $this->variant->getProduct();
@@ -34,17 +60,33 @@ public function getProduct(): ?ProductInterface
/**
* {@inheritdoc}
*/
- public function getVariant(): ?ProductVariantInterface
+ public function getProductName(): ?string
{
- return $this->variant;
+ return $this->productName ?: $this->variant->getProduct()->getName();
}
/**
* {@inheritdoc}
*/
- public function setVariant(?ProductVariantInterface $variant): void
+ public function setProductName(?string $productName): void
{
- $this->variant = $variant;
+ $this->productName = $productName;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getVariantName(): ?string
+ {
+ return $this->variantName ?: $this->variant->getName();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setVariantName(?string $variantName): void
+ {
+ $this->variantName = $variantName;
}
/**
diff --git a/src/Sylius/Component/Core/Model/OrderItemInterface.php b/src/Sylius/Component/Core/Model/OrderItemInterface.php
index 24442f3a987..66ee73dc1e1 100644
--- a/src/Sylius/Component/Core/Model/OrderItemInterface.php
+++ b/src/Sylius/Component/Core/Model/OrderItemInterface.php
@@ -32,6 +32,26 @@ public function getVariant(): ?ProductVariantInterface;
*/
public function setVariant(?ProductVariantInterface $variant): void;
+ /**
+ * @return string|null
+ */
+ public function getProductName(): ?string;
+
+ /**
+ * @param string|null $productName
+ */
+ public function setProductName(?string $productName): void;
+
+ /**
+ * @return string|null
+ */
+ public function getVariantName(): ?string;
+
+ /**
+ * @param string|null $variantName
+ */
+ public function setVariantName(?string $variantName): void;
+
/**
* @return int
*/
diff --git a/src/Sylius/Component/Core/Order/OrderItemNamesSetter.php b/src/Sylius/Component/Core/Order/OrderItemNamesSetter.php
new file mode 100644
index 00000000000..7f314359918
--- /dev/null
+++ b/src/Sylius/Component/Core/Order/OrderItemNamesSetter.php
@@ -0,0 +1,41 @@
+getLocaleCode();
+
+ /** @var OrderItemInterface $item */
+ foreach ($order->getItems() as $item) {
+ $variant = $item->getVariant();
+
+ if (null !== $variant) {
+ $item->setVariantName($variant->getTranslation($localeCode)->getName());
+ }
+
+ if (null !== $variant && null !== $variant->getProduct()) {
+ $item->setProductName($variant->getProduct()->getTranslation($localeCode)->getName());
+ }
+ }
+ }
+}
diff --git a/src/Sylius/Component/Core/Order/OrderItemNamesSetterInterface.php b/src/Sylius/Component/Core/Order/OrderItemNamesSetterInterface.php
new file mode 100644
index 00000000000..7973898fe3a
--- /dev/null
+++ b/src/Sylius/Component/Core/Order/OrderItemNamesSetterInterface.php
@@ -0,0 +1,24 @@
+getSubtotal()->shouldReturn(19000);
}
+
+ function it_has_no_variant_by_default(): void
+ {
+ $this->getVariant()->shouldReturn(null);
+ }
}
diff --git a/src/Sylius/Component/Core/spec/Order/OrderItemNamesSetterSpec.php b/src/Sylius/Component/Core/spec/Order/OrderItemNamesSetterSpec.php
new file mode 100644
index 00000000000..7d18efe76e6
--- /dev/null
+++ b/src/Sylius/Component/Core/spec/Order/OrderItemNamesSetterSpec.php
@@ -0,0 +1,56 @@
+shouldImplement(OrderItemNamesSetterInterface::class);
+ }
+
+ function it_sets_product_and_product_variant_names_on_order_items(
+ OrderInterface $order,
+ OrderItemInterface $orderItem,
+ ProductVariantInterface $variant,
+ ProductVariantTranslationInterface $variantTranslation,
+ ProductInterface $product,
+ ProductTranslationInterface $productTranslation
+ ): void {
+ $order->getLocaleCode()->willReturn('en_US');
+ $order->getItems()->willReturn(new ArrayCollection([$orderItem->getWrappedObject()]));
+
+ $variant->getProduct()->willReturn($product);
+ $variant->getTranslation('en_US')->willReturn($variantTranslation);
+ $variantTranslation->getName()->willReturn('Variant name');
+
+ $product->getTranslation('en_US')->willReturn($productTranslation);
+ $productTranslation->getName()->willReturn('Product name');
+
+ $orderItem->setVariantName('Variant name');
+ $orderItem->setProductName('Product name');
+
+ $this->__invoke($order);
+ }
+}
diff --git a/tests/DataFixtures/ORM/resources/cart_with_items.yml b/tests/DataFixtures/ORM/resources/cart_with_items.yml
index 952558a530d..7713795c37f 100644
--- a/tests/DataFixtures/ORM/resources/cart_with_items.yml
+++ b/tests/DataFixtures/ORM/resources/cart_with_items.yml
@@ -1,60 +1,3 @@
-Sylius\Component\Core\Model\Order:
- cart_with_items:
- channel: "@channel_web"
- addItem: ["@sw_mug_item", "@hard_available_mug_item"]
- currencyCode: "USD"
- localeCode: "en_US"
- customer: "@customer_oliver"
- state: "cart"
-
-Sylius\Component\Core\Model\OrderItem:
- sw_mug_item:
- quantity: 2
- addUnit: ["@sw_mug_item_unit1", "@sw_mug_item_unit2"]
- variant: "@mug_sw"
- order: "@cart_with_items"
- hard_available_mug_item:
- quantity: 1
- addUnit: ["@hard_available_mug_item_unit"]
- variant: "@hard_available_mug"
- order: "@cart_with_items"
-
-Sylius\Component\Core\Model\OrderItemUnit:
- sw_mug_item_unit1:
- __construct: ["@sw_mug_item"]
- sw_mug_item_unit2:
- __construct: ["@sw_mug_item"]
- hard_available_mug_item_unit:
- __construct: ["@hard_available_mug_item"]
-
-Sylius\Component\Core\Model\Channel:
- channel_web:
- code: "WEB"
- name: "Web Channel"
- hostname: "localhost"
- description: "Lorem ipsum"
- baseCurrency: "@currency"
- defaultLocale: "@locale"
- color: "black"
- enabled: true
- taxCalculationStrategy: "order_items_based"
-
-Sylius\Component\Currency\Model\Currency:
- currency:
- code: "USD"
-
-Sylius\Component\Locale\Model\Locale:
- locale:
- code: "en_US"
-
-Sylius\Component\Core\Model\Customer:
- customer_oliver:
- firstName: "Oliver"
- lastName: "Queen"
- email: "oliver.queen@star-city.com"
- emailCanonical: "oliver.queen@star-city.com"
- birthday: "<(new \\DateTime())>"
-
Sylius\Component\Core\Model\Product:
mug:
code: "MUG"
@@ -125,6 +68,63 @@ Sylius\Component\Product\Model\ProductVariantTranslation:
name: "Breaking bad mug"
translatable: "@hard_available_mug"
+Sylius\Component\Core\Model\Order:
+ cart_with_items:
+ channel: "@channel_web"
+ addItem: ["@sw_mug_item", "@hard_available_mug_item"]
+ currencyCode: "USD"
+ localeCode: "en_US"
+ customer: "@customer_oliver"
+ state: "cart"
+
+Sylius\Component\Core\Model\OrderItem:
+ sw_mug_item:
+ quantity: 2
+ addUnit: ["@sw_mug_item_unit1", "@sw_mug_item_unit2"]
+ variant: "@mug_sw"
+ order: "@cart_with_items"
+ hard_available_mug_item:
+ quantity: 1
+ addUnit: ["@hard_available_mug_item_unit"]
+ variant: "@hard_available_mug"
+ order: "@cart_with_items"
+
+Sylius\Component\Core\Model\OrderItemUnit:
+ sw_mug_item_unit1:
+ __construct: ["@sw_mug_item"]
+ sw_mug_item_unit2:
+ __construct: ["@sw_mug_item"]
+ hard_available_mug_item_unit:
+ __construct: ["@hard_available_mug_item"]
+
+Sylius\Component\Core\Model\Channel:
+ channel_web:
+ code: "WEB"
+ name: "Web Channel"
+ hostname: "localhost"
+ description: "Lorem ipsum"
+ baseCurrency: "@currency"
+ defaultLocale: "@locale"
+ color: "black"
+ enabled: true
+ taxCalculationStrategy: "order_items_based"
+
+Sylius\Component\Currency\Model\Currency:
+ currency:
+ code: "USD"
+
+Sylius\Component\Locale\Model\Locale:
+ locale:
+ code: "en_US"
+
+Sylius\Component\Core\Model\Customer:
+ customer_oliver:
+ firstName: "Oliver"
+ lastName: "Queen"
+ email: "oliver.queen@star-city.com"
+ emailCanonical: "oliver.queen@star-city.com"
+ birthday: "<(new \\DateTime())>"
+
Sylius\Component\Core\Model\ChannelPricing:
sw_mug_web_channel_pricing:
channelCode: "WEB"