Skip to content

Commit

Permalink
fix(SW-27165): Change consideration of graduated prices in order module
Browse files Browse the repository at this point in the history
While adding new positions to an existing order in the backend order module, graduated prices are still considered.
If an existing position is changed, the graduated price will only be checked and considered if the quantity was changed.
With this change it is possible again to also set a custom price for a position that contains a product with graduated prices.
  • Loading branch information
mitelg committed Sep 21, 2023
1 parent e02c2a5 commit 08660ed
Show file tree
Hide file tree
Showing 2 changed files with 117 additions and 14 deletions.
31 changes: 18 additions & 13 deletions engine/Shopware/Controllers/Backend/Order.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
*/
Expand Down Expand Up @@ -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);
}

Expand Down Expand Up @@ -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();

Expand Down
100 changes: 99 additions & 1 deletion tests/Functional/Controllers/Backend/OrderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ protected function setUp(): void
{
$this->connection = $this->getContainer()->get(Connection::class);
$this->authPlugin = $this->getContainer()->get('plugins')->Backend()->Auth();
$this->modelManager = $this->getContainer()->get(ModelManager::class);
$this->modelManager = Shopware()->Container()->get(ModelManager::class);
}

/**
Expand Down Expand Up @@ -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<array{params: array{quantity?: int, price?: float, total?: float}, expectedValues: array{price: float, total: float}}>
*/
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
*/
Expand Down

0 comments on commit 08660ed

Please sign in to comment.