* @copyright Since 2007 PrestaShop SA and Contributors * @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) */ namespace PrestaShop\PrestaShop\Adapter\Order\CommandHandler; use Address; use Cart; use Configuration; use Context; use Country; use Currency; use Customer; use Order; use OrderDetail; use Pack; use PrestaShop\PrestaShop\Adapter\ContextStateManager; use PrestaShop\PrestaShop\Adapter\Order\AbstractOrderHandler; use PrestaShop\PrestaShop\Adapter\StockManager; use PrestaShop\PrestaShop\Core\Domain\Order\Exception\OrderException; use Product; use Shop; use StockAvailable; use StockManagerFactory; use StockMvt; use Warehouse; /** * Abstracts reusable functionality for Order subdomain handlers. * * @internal */ abstract class AbstractOrderCommandHandler extends AbstractOrderHandler { /** * @param OrderDetail $orderDetail * @param int $productQuantity * @param bool $delete */ protected function reinjectQuantity(OrderDetail $orderDetail, $productQuantity, $delete = false) { // Reinject product $reinjectableQuantity = (int) $orderDetail->product_quantity - (int) $orderDetail->product_quantity_reinjected; $quantityToReinject = $productQuantity > $reinjectableQuantity ? $reinjectableQuantity : $productQuantity; $product = new Product( $orderDetail->product_id, false, (int) Context::getContext()->language->id, (int) $orderDetail->id_shop ); if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') && $product->advanced_stock_management && $orderDetail->id_warehouse != 0 ) { $manager = StockManagerFactory::getManager(); $movements = StockMvt::getNegativeStockMvts( $orderDetail->id_order, $orderDetail->product_id, $orderDetail->product_attribute_id, $quantityToReinject ); foreach ($movements as $movement) { if ($quantityToReinject > $movement['physical_quantity']) { $quantityToReinject = $movement['physical_quantity']; } if (Pack::isPack((int) $product->id)) { // Gets items if ($product->pack_stock_type == Pack::STOCK_TYPE_PRODUCTS_ONLY || $product->pack_stock_type == Pack::STOCK_TYPE_PACK_BOTH || ($product->pack_stock_type == Pack::STOCK_TYPE_DEFAULT && Configuration::get('PS_PACK_STOCK_TYPE') > 0) ) { $products_pack = Pack::getItems((int) $product->id, (int) Configuration::get('PS_LANG_DEFAULT')); // Foreach item foreach ($products_pack as $product_pack) { if ($product_pack->advanced_stock_management == 1) { $manager->addProduct( $product_pack->id, $product_pack->id_pack_product_attribute, new Warehouse($movement['id_warehouse']), $product_pack->pack_quantity * $quantityToReinject, null, $movement['price_te'] ); } } } if ($product->pack_stock_type == Pack::STOCK_TYPE_PACK_ONLY || $product->pack_stock_type == Pack::STOCK_TYPE_PACK_BOTH || ( $product->pack_stock_type == Pack::STOCK_TYPE_DEFAULT && (Configuration::get('PS_PACK_STOCK_TYPE') == Pack::STOCK_TYPE_PACK_ONLY || Configuration::get('PS_PACK_STOCK_TYPE') == Pack::STOCK_TYPE_PACK_BOTH) ) ) { $manager->addProduct( $orderDetail->product_id, $orderDetail->product_attribute_id, new Warehouse($movement['id_warehouse']), $quantityToReinject, null, $movement['price_te'] ); } } else { $manager->addProduct( $orderDetail->product_id, $orderDetail->product_attribute_id, new Warehouse($movement['id_warehouse']), $quantityToReinject, null, $movement['price_te'] ); } } $productId = $orderDetail->product_id; if ($delete) { $orderDetail->delete(); } StockAvailable::synchronize($productId); } elseif ($orderDetail->id_warehouse == 0) { StockAvailable::updateQuantity( $orderDetail->product_id, $orderDetail->product_attribute_id, $quantityToReinject, $orderDetail->id_shop, true, [ 'id_order' => $orderDetail->id_order, 'id_stock_mvt_reason' => Configuration::get('PS_STOCK_CUSTOMER_RETURN_REASON'), ] ); // sync all stock (new StockManager())->updatePhysicalProductQuantity( (int) $orderDetail->id_shop, (int) Configuration::get('PS_OS_ERROR'), (int) Configuration::get('PS_OS_CANCELED'), null, (int) $orderDetail->id_order ); if ($delete) { $orderDetail->delete(); } } else { throw new OrderException('This product cannot be re-stocked.'); } } /** * @param ContextStateManager $contextStateManager * @param Cart $cart */ protected function setCartContext(ContextStateManager $contextStateManager, Cart $cart): void { $contextStateManager ->saveCurrentContext() ->setCart($cart) ->setCustomer(new Customer($cart->id_customer)) ->setCurrency(new Currency($cart->id_currency)) ->setLanguage($cart->getAssociatedLanguage()) ->setCountry($this->getCartTaxCountry($cart)) ->setShop(new Shop($cart->id_shop)) ; } /** * @param ContextStateManager $contextStateManager * @param Order $order */ protected function setOrderContext(ContextStateManager $contextStateManager, Order $order): void { $cart = new Cart($order->id_cart); $this->setCartContext($contextStateManager, $cart); } /** * @param Cart $cart * * @return Country * * @throws \PrestaShopDatabaseException * @throws \PrestaShopException */ protected function getCartTaxCountry(Cart $cart): Country { $taxAddressType = Configuration::get('PS_TAX_ADDRESS_TYPE'); $taxAddressId = property_exists($cart, $taxAddressType) ? $cart->{$taxAddressType} : $cart->id_address_delivery; $taxAddress = new Address($taxAddressId); return new Country($taxAddress->id_country); } }