Skip to content

Commit

Permalink
Merge pull request #29132 from FabienPapet/fix-product-combination-stock
Browse files Browse the repository at this point in the history
Fix stock policy propagation on product combination
  • Loading branch information
jolelievre committed Nov 16, 2022
2 parents c5f3ac2 + e85338a commit bd20f7a
Show file tree
Hide file tree
Showing 9 changed files with 153 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,13 @@
use PrestaShop\PrestaShop\Core\Domain\Product\Combination\Exception\CannotDeleteCombinationException;
use PrestaShop\PrestaShop\Core\Domain\Product\Combination\Exception\CombinationNotFoundException;
use PrestaShop\PrestaShop\Core\Domain\Product\Combination\ValueObject\CombinationId;
use PrestaShop\PrestaShop\Core\Domain\Product\Stock\ValueObject\OutOfStockType;
use PrestaShop\PrestaShop\Core\Domain\Product\ValueObject\ProductId;
use PrestaShop\PrestaShop\Core\Domain\Shop\ValueObject\ShopConstraint;
use PrestaShop\PrestaShop\Core\Exception\CoreException;
use PrestaShop\PrestaShop\Core\Grid\Query\ProductCombinationQueryBuilder;
use PrestaShop\PrestaShop\Core\Repository\AbstractObjectModelRepository;
use PrestaShop\PrestaShop\Core\Repository\ShopConstraintTrait;
use PrestaShop\PrestaShop\Core\Search\Filters\ProductCombinationFilters;
use PrestaShopException;
use Product;
Expand All @@ -51,6 +54,8 @@
*/
class CombinationRepository extends AbstractObjectModelRepository
{
use ShopConstraintTrait;

/**
* @var Connection
*/
Expand Down Expand Up @@ -366,4 +371,17 @@ public function getCombinationIdsByAttributes(ProductId $productId, array $attri
return new CombinationId((int) $combination['id_product_attribute']);
}, $result);
}

public function updateCombinationStock(ProductId $productId, OutOfStockType $outOfStockType, ShopConstraint $shopConstraint = null): void
{
$qb = $this->connection->createQueryBuilder();
$qb
->update(sprintf('%sstock_available', $this->dbPrefix), 'ps')
->set('ps.out_of_stock', (string) $outOfStockType->getValue())
->where('ps.id_product = :productId')
->setParameter('productId', $productId->getValue())
;

$this->applyShopConstraint($qb, $shopConstraint)->execute();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@ public function __construct(
$this->lowStockThreshold = $lowStockThreshold;
$this->lowStockAlertEnabled = $lowStockAlertEnabled;
$this->availableDate = $availableDate;
$this->stockModification = $stockModification;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

namespace PrestaShop\PrestaShop\Adapter\Product\Stock\CommandHandler;

use PrestaShop\PrestaShop\Adapter\Product\Combination\Repository\CombinationRepository;
use PrestaShop\PrestaShop\Adapter\Product\Stock\Repository\MovementReasonRepository;
use PrestaShop\PrestaShop\Adapter\Product\Stock\Update\ProductStockProperties;
use PrestaShop\PrestaShop\Adapter\Product\Stock\Update\ProductStockUpdater;
Expand All @@ -50,16 +51,24 @@ final class UpdateProductStockInformationHandler implements UpdateProductStockIn
*/
private $movementReasonRepository;

/**
* @var CombinationRepository
*/
private $combinationRepository;

/**
* @param ProductStockUpdater $productStockUpdater
* @param MovementReasonRepository $movementReasonRepository
* @param CombinationRepository $combinationRepository
*/
public function __construct(
ProductStockUpdater $productStockUpdater,
MovementReasonRepository $movementReasonRepository
MovementReasonRepository $movementReasonRepository,
CombinationRepository $combinationRepository
) {
$this->productStockUpdater = $productStockUpdater;
$this->movementReasonRepository = $movementReasonRepository;
$this->combinationRepository = $combinationRepository;
}

/**
Expand Down Expand Up @@ -91,5 +100,9 @@ public function handle(UpdateProductStockInformationCommand $command): void
),
$command->getShopConstraint()
);

if (null !== $command->getOutOfStockType()) {
$this->combinationRepository->updateCombinationStock($command->getProductId(), $command->getOutOfStockType(), $command->getShopConstraint());
}
}
}
60 changes: 60 additions & 0 deletions src/Core/Repository/ShopConstraintTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/

declare(strict_types=1);

namespace PrestaShop\PrestaShop\Core\Repository;

use Doctrine\DBAL\Query\QueryBuilder;
use PrestaShop\PrestaShop\Core\Domain\Shop\ValueObject\ShopConstraint;

trait ShopConstraintTrait
{
protected function applyShopConstraint(
QueryBuilder $queryBuilder,
?ShopConstraint $shopConstraint = null
): QueryBuilder {
if (null === $shopConstraint) {
return $queryBuilder;
}

if ($shopConstraint->getShopId() !== null) {
$queryBuilder
->andWhere('id_shop = :shop')
->setParameter('shop', $shopConstraint->getShopId()->getValue())
;
}

if ($shopConstraint->getShopGroupId() !== null) {
$queryBuilder
->andWhere('id_shop_group = :shop_group')
->setParameter('shop_group', $shopConstraint->getShopGroupId()->getValue())
;
}

return $queryBuilder;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ services:
arguments:
- '@prestashop.adapter.product.stock.update.product_stock_updater'
- '@prestashop.adapter.product.stock.repository.movement_reason_repository'
- '@prestashop.adapter.product.combination.repository.combination_repository'
tags:
- name: tactician.handler
command: PrestaShop\PrestaShop\Core\Domain\Product\Stock\Command\UpdateProductStockInformationCommand
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
use PrestaShop\PrestaShop\Core\Domain\Product\Customization\QueryResult\CustomizationField;
use PrestaShop\PrestaShop\Core\Domain\Product\Query\GetProductForEditing;
use PrestaShop\PrestaShop\Core\Domain\Product\QueryResult\ProductForEditing;
use PrestaShop\PrestaShop\Core\Domain\Product\Stock\ValueObject\OutOfStockType;
use PrestaShop\PrestaShop\Core\Domain\Shop\ValueObject\ShopConstraint;
use PrestaShop\PrestaShop\Core\Util\DateTime\DateTime as DateTimeUtil;
use RuntimeException;
Expand Down Expand Up @@ -312,6 +313,23 @@ protected function extractValueFromProductForEditing(ProductForEditing $productF
return $propertyAccessor->getValue($productForEditing, $pathsByNames[$propertyName]);
}

/**
* @param string $outOfStock
*
* @return int
*/
protected function convertOutOfStockToInt(string $outOfStock): int
{
$intValues = [
'default' => OutOfStockType::OUT_OF_STOCK_DEFAULT,
'available' => OutOfStockType::OUT_OF_STOCK_AVAILABLE,
'not_available' => OutOfStockType::OUT_OF_STOCK_NOT_AVAILABLE,
'invalid' => 42, // This random number is hardcoded intentionally to reflect invalid stock type
];

return $intValues[$outOfStock];
}

/**
* @return int
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
use PrestaShop\PrestaShop\Core\Domain\Product\Combination\QueryResult\CombinationStock;
use PrestaShop\PrestaShop\Core\Domain\Product\Stock\Exception\ProductStockConstraintException;
use PrestaShop\PrestaShop\Core\Util\DateTime\DateTime as DateTimeUtil;
use StockAvailable;
use Tests\Integration\Behaviour\Features\Context\Util\PrimitiveUtils;

class UpdateCombinationStockFeatureContext extends AbstractCombinationFeatureContext
Expand Down Expand Up @@ -173,4 +174,32 @@ private function fillCommand(UpdateCombinationStockCommand $command, array $data
$command->setAvailableDate(new DateTime($dataRows['available date']));
}
}

/**
* @Then /^all combinations of product "([^"]*)" should have the stock policy to "([^"]*)"$/
*/
public function allCombinationsOfProductShouldHaveTheStockPolicyTo(string $reference, string $outOfStock)
{
$product = $this->getProductForEditing($reference);

$outOfStockInt = $this->convertOutOfStockToInt($outOfStock);
Assert::assertSame(
$product->getStockInformation()->getOutOfStockType(),
$outOfStockInt
);

$combinations = $this->getCombinationsList($reference);

foreach ($combinations->getCombinations() as $combination) {
$id = StockAvailable::getStockAvailableIdByProductId(
$this->getSharedStorage()->get($reference),
$combination->getCombinationId()
);

Assert::assertSame(
(int) (new StockAvailable($id))->out_of_stock,
$outOfStockInt
);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@
use PrestaShop\PrestaShop\Core\Domain\Product\Stock\Query\GetEmployeesStockMovements;
use PrestaShop\PrestaShop\Core\Domain\Product\Stock\QueryResult\EmployeeStockMovement;
use PrestaShop\PrestaShop\Core\Domain\Product\Stock\QueryResult\StockMovement;
use PrestaShop\PrestaShop\Core\Domain\Product\Stock\ValueObject\OutOfStockType;
use PrestaShop\PrestaShop\Core\Domain\Product\Stock\ValueObject\StockId;
use PrestaShop\PrestaShop\Core\Domain\Shop\ValueObject\ShopConstraint;
use PrestaShopBundle\Api\QueryStockMovementParamsCollection;
Expand Down Expand Up @@ -448,23 +447,6 @@ private function setUpdateStockCommandData(array $data, UpdateProductStockInform
return $data;
}

/**
* @param string $outOfStock
*
* @return int
*/
private function convertOutOfStockToInt(string $outOfStock): int
{
$intValues = [
'default' => OutOfStockType::OUT_OF_STOCK_DEFAULT,
'available' => OutOfStockType::OUT_OF_STOCK_AVAILABLE,
'not_available' => OutOfStockType::OUT_OF_STOCK_NOT_AVAILABLE,
'invalid' => 42, // This random number is hardcoded intentionally to reflect invalid stock type
];

return $intValues[$outOfStock];
}

/**
* @param string $outOfStock
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -234,3 +234,16 @@ Feature: Update product combination stock information in Back Office (BO)
| location | |
| available date | |
And product "product1" should have no stock movements

Scenario: I update product out of stock
And product "product1" should have following stock information:
| out_of_stock_type | default |
When I update product "product1" stock with following information:
| out_of_stock_type | available |
Then all combinations of product "product1" should have the stock policy to "available"
When I update product "product1" stock with following information:
| out_of_stock_type | default |
Then all combinations of product "product1" should have the stock policy to "default"
When I update product "product1" stock with following information:
| out_of_stock_type | not_available |
Then all combinations of product "product1" should have the stock policy to "not_available"

0 comments on commit bd20f7a

Please sign in to comment.