diff --git a/engine/Shopware/Controllers/Backend/Order.php b/engine/Shopware/Controllers/Backend/Order.php index e24e110db9b..71f9b742001 100644 --- a/engine/Shopware/Controllers/Backend/Order.php +++ b/engine/Shopware/Controllers/Backend/Order.php @@ -117,7 +117,7 @@ class Shopware_Controllers_Backend_Order extends Shopware_Controllers_Backend_Ex /** * @deprecated - Will be removed in Shopware 5.8 without a replacement - * Contains the dynamic receipt repository + * Contains the order document repository * * @var OrderDocumentRepository */ @@ -1950,7 +1950,17 @@ private function getPositionAssociatedData(array $data, Order $order): array $shopContext = $this->createShopContext($order); $data = $this->checkTaxRule($data, $shopContext); - if ($this->hasProductGraduatedPrices($data['articleNumber'], $order)) { + $orderPosition = null; + foreach ($order->getDetails() as $position) { + if ($position->getId() === (int) $data['id']) { + $orderPosition = $position; + break; + } + } + // Only get graduated price if a new position should be added or quantity has changed + if (($orderPosition === null || $orderPosition->getQuantity() !== (int) $data['quantity']) + && $this->hasProductGraduatedPrices($data['articleNumber'], $order) + ) { $data = $this->checkPrice($data, $order, $shopContext); } @@ -2106,20 +2116,15 @@ private function checkTaxRule(array $data, ShopContextInterface $shopContext): a return $data; } - private function hasProductGraduatedPrices(string $productNumber, ORDER $order): bool + private function hasProductGraduatedPrices(string $productNumber, Order $order): bool { $customerGroupKey = $this->getCustomerGroupKey($order); - $sql = 'SELECT - prices.pricegroup, count(*) - FROM - s_articles_prices AS prices - INNER JOIN - s_articles_details ON prices.articledetailsID = s_articles_details.id - WHERE - s_articles_details.ordernumber = :productNumber - GROUP BY - prices.pricegroup;'; + $sql = 'SELECT prices.pricegroup, count(*) + FROM s_articles_prices AS prices + INNER JOIN s_articles_details ON prices.articledetailsID = s_articles_details.id + WHERE s_articles_details.ordernumber = :productNumber + GROUP BY prices.pricegroup;'; $result = $this->container->get(Connection::class)->executeQuery($sql, ['productNumber' => $productNumber])->fetchAllKeyValue(); diff --git a/tests/Functional/Controllers/Backend/OrderTest.php b/tests/Functional/Controllers/Backend/OrderTest.php index 4e437173b86..9c6ed5c9935 100644 --- a/tests/Functional/Controllers/Backend/OrderTest.php +++ b/tests/Functional/Controllers/Backend/OrderTest.php @@ -369,6 +369,104 @@ public function provideProductParamsForSavePositionActionTestingGraduatedPrices( ]; } + /** + * @dataProvider provideProductParamsForSavePositionActionOnExistingPosition + * + * @param array{quantity?: int, price?: float, total?: float} $params + * @param array{price: float, total: float} $expectedValues + */ + public function testSavePositionActionReturnValuesForGraduatedPricesOnExistingPosition(array $params, array $expectedValues): void + { + $order = $this->modelManager->getRepository(Order::class)->findOneBy([]); + static::assertInstanceOf(Order::class, $order); + $newPositionParams = [ + 'id' => 0, + 'orderId' => $order->getId(), + 'articleNumber' => self::PRODUCT_GRADUATED_PRICES_DEMODATA_ORDER_NUMBER, + 'articleName' => self::PRODUCT_GRADUATED_PRICES_DEMODATA_NAME, + 'articleId' => self::PRODUCT_GRADUATED_PRICES_DEMODATA_PRODUCT_ID, + 'articleDetailId' => self::PRODUCT_GRADUATED_PRICES_DEMODATA_PRODUCT_VARIANT_ID, + 'mode' => 0, + 'quantity' => 2, + 'statusId' => 0, + 'statusDescription' => '', + 'taxId' => 1, + 'taxRate' => 19.0, + 'taxDescription' => '', + 'inStock' => 0, + 'changed' => $order->getChanged() ? $order->getChanged()->format(DateTimeInterface::ATOM) : '', + ]; + + $request = new Enlight_Controller_Request_RequestTestCase(); + $request->setParams($newPositionParams); + + $controller = $this->getController(); + $controller->setRequest($request); + $controller->savePositionAction(); + $results = $controller->View()->getAssign(); + + static::assertTrue($results['success'], $results['message'] ?? ''); + static::assertSame(0.84, $results['data']['price']); + static::assertSame(1.68, $results['data']['total']); + + $this->modelManager->refresh($order); + $changeQuantityParams = [ + 'id' => $results['data']['id'], + 'price' => $results['data']['price'], + 'total' => $results['data']['total'], + 'changed' => $order->getChanged() ? $order->getChanged()->format(DateTimeInterface::ATOM) : '', + ]; + $changeQuantityParams = array_merge($newPositionParams, $changeQuantityParams, $params); + + $request = new Enlight_Controller_Request_RequestTestCase(); + $request->setParams($changeQuantityParams); + + $controller->setRequest($request); + $controller->savePositionAction(); + $results = $controller->View()->getAssign(); + + static::assertTrue($results['success'], $results['message'] ?? ''); + static::assertSame($expectedValues['price'], $results['data']['price']); + static::assertSame($expectedValues['total'], $results['data']['total']); + } + + /** + * @return Generator + */ + public function provideProductParamsForSavePositionActionOnExistingPosition(): Generator + { + yield 'Only change quantity, graduated price should be considered' => [ + 'params' => [ + 'quantity' => 20, + ], + 'expectedValues' => [ + 'price' => 0.76, + 'total' => 15.2, + ], + ]; + yield 'Only change price, graduated price should be ignored' => [ + 'params' => [ + 'price' => 0.15, + 'total' => 0.30, + ], + 'expectedValues' => [ + 'price' => 0.15, + 'total' => 0.30, + ], + ]; + yield 'Change quantity and price, graduated price should be considered' => [ + 'params' => [ + 'quantity' => 30, + 'price' => 0.15, + 'total' => 0.30, + ], + 'expectedValues' => [ + 'price' => 0.67, + 'total' => 20.1, + ], + ]; + } + /** * @dataProvider provideTaxRuleParams */