511 lines
18 KiB
PHP
511 lines
18 KiB
PHP
<?php
|
|
|
|
namespace KupShop\ContentBundle\View;
|
|
|
|
use KupShop\GraphQLBundle\EventListener\JsShopRefreshListener;
|
|
use KupShop\KupShopBundle\Context\ContextManager;
|
|
use KupShop\KupShopBundle\Exception\RedirectException;
|
|
use KupShop\KupShopBundle\Util\Functional\Mapping;
|
|
use KupShop\KupShopBundle\Views\Traits\RequestTrait;
|
|
use KupShop\KupShopBundle\Views\View;
|
|
use KupShop\OrderDiscountBundle\Util\DiscountManager;
|
|
use KupShop\OrderingBundle\Event\OrderEvent;
|
|
use KupShop\OrderingBundle\OrderDelivery;
|
|
use KupShop\OrderingBundle\Util\Order\OrderInfo;
|
|
use KupShop\OrderingBundle\Util\Purchase\PurchaseUtil;
|
|
use KupShop\ProductsChargesBundle\Actions\Frontend\OrdersChargesHandler;
|
|
use Query\Operator;
|
|
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
|
use Symfony\Component\HttpFoundation\RedirectResponse;
|
|
use Symfony\Component\HttpFoundation\Request;
|
|
use Symfony\Component\HttpFoundation\Session\SessionInterface;
|
|
use Symfony\Contracts\Service\Attribute\Required;
|
|
|
|
class OrderEditView extends View
|
|
{
|
|
use RequestTrait;
|
|
|
|
protected string $smartyFallback = 'account';
|
|
protected string $entrypoint = 'account';
|
|
|
|
protected $template = 'orderEdit.tpl';
|
|
|
|
protected $orderId;
|
|
|
|
protected $user;
|
|
|
|
/** @var \Order|null */
|
|
protected $order;
|
|
|
|
/** @var OrderDelivery */
|
|
protected $orderDelivery;
|
|
|
|
#[Required]
|
|
public PurchaseUtil $purchaseUtil;
|
|
|
|
public DiscountManager $discountManager;
|
|
|
|
#[Required]
|
|
public OrderInfo $orderInfo;
|
|
|
|
public function __construct(
|
|
protected SessionInterface $session,
|
|
private ContextManager $contextManager,
|
|
private EventDispatcherInterface $eventDispatcher,
|
|
private \Cart $cart,
|
|
) {
|
|
$this->user = \User::getCurrentUser();
|
|
}
|
|
|
|
public function getResponse(?Request $request = null)
|
|
{
|
|
if (!findModule('order_edit')) {
|
|
redirection('MODUL_NOT_FOUND');
|
|
}
|
|
|
|
if ($this->orderId === null || $this->orderId == 0) {
|
|
return new RedirectResponse(
|
|
createScriptURL([
|
|
'URL' => 'launch.php',
|
|
's' => 'orders',
|
|
'ESCAPE' => 'NO',
|
|
])
|
|
);
|
|
}
|
|
|
|
$this->checkUser();
|
|
|
|
return parent::getResponse($request);
|
|
}
|
|
|
|
public function getBodyVariables()
|
|
{
|
|
$vars = parent::getBodyVariables();
|
|
|
|
$this->contextManager->activateOrder($this->getOrder(), function () use (&$vars) {
|
|
$vars += $this->editOrder();
|
|
});
|
|
|
|
return $vars;
|
|
}
|
|
|
|
public function getTitle()
|
|
{
|
|
return str_replace('%ORDERNO', $this->order->order_no, translate('title', 'orderView'));
|
|
}
|
|
|
|
public function getBreadcrumbs()
|
|
{
|
|
$url = createScriptURL([
|
|
'URL' => 'launch.php',
|
|
's' => 'orders',
|
|
]);
|
|
|
|
return getReturnNavigation(-1, 'NO_TYPE', [['link' => $url, 'text' => translate('returnNav', 'orderView')[0]], ['text' => translate('returnNav', 'orderView')[1]]]);
|
|
}
|
|
|
|
public function getWpjToolbar()
|
|
{
|
|
$arr = [
|
|
'url' => getAdminUrl('orders', ['ID' => $this->orderId]),
|
|
'title' => 'Upravit objednávku',
|
|
];
|
|
|
|
return array_merge(parent::getWpjToolbar(), $arr);
|
|
}
|
|
|
|
private function getOrder()
|
|
{
|
|
if (!$this->order) {
|
|
$this->order = new \Order();
|
|
$this->order->setEditMode();
|
|
$this->order->createFromDB($this->orderId);
|
|
}
|
|
|
|
return $this->order;
|
|
}
|
|
|
|
/** @required */
|
|
public function setOrderDelivery(OrderDelivery $orderDelivery)
|
|
{
|
|
$this->orderDelivery = $orderDelivery;
|
|
}
|
|
|
|
public function recalculateDelivery()
|
|
{
|
|
return $this->orderDelivery->recalculateDelivery($this->order, $this->order->getDeliveryId());
|
|
}
|
|
|
|
private function editOrder()
|
|
{
|
|
$pageVars = [];
|
|
|
|
$originalOrder = new \Order();
|
|
$originalOrder->createFromDB($this->orderId);
|
|
|
|
$pageVars['order'] = $this->order;
|
|
$pageVars['editable'] = $this->order->isEditable();
|
|
|
|
if ($pageVars['editable'] > 0) {
|
|
// Check there are no negative pieces (returns)
|
|
foreach ($originalOrder->fetchItems() as $item) {
|
|
if ($item['pieces'] < 0) {
|
|
$pageVars['editable'] = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($pageVars['editable'] == 0) {
|
|
$this->addErrorMessage('Tato objednávka bohužel nejde upravovat.');
|
|
throw new RedirectException(
|
|
createScriptURL([
|
|
'URL' => 'launch.php',
|
|
's' => 'orderView',
|
|
'IDo' => $this->orderId,
|
|
'cf' => $this->request->get('cf'),
|
|
])
|
|
);
|
|
}
|
|
|
|
if ($pageVars['editable'] == 1) {
|
|
sqlQuery('DELETE FROM '.getTableName('order_edit')." WHERE id_order='{$this->orderId}'");
|
|
|
|
sqlQuery('INSERT INTO '.getTableName('order_edit').'
|
|
SELECT NULL, id, id_order, id_product, id_variation, id_parent, pieces, pieces_reserved, piece_price, total_price, descr, tax, NOW(), note, discount '
|
|
.(findModule(\Modules::PRODUCTS, \Modules::SUB_PRICE_BUY) ? ', price_buy' : '').'
|
|
FROM '.getTableName('order_items')."
|
|
WHERE id_order='{$this->orderId}' AND total_price != 0");
|
|
|
|
$pageVars['editable'] = 2;
|
|
}
|
|
|
|
if (in_array($this->getAcn(), ['recount', 'deleteItem', 'send', 'addCart'])) {
|
|
switch ($this->getAcn()) {
|
|
case 'addCart':
|
|
$this->addCart();
|
|
break;
|
|
case 'deleteItem':
|
|
$this->deleteItem();
|
|
break;
|
|
default:
|
|
$pieces = $this->getPieces();
|
|
// update item
|
|
foreach ($pieces as $IDitem => $piece) {
|
|
if (is_numeric($piece) && intval($piece) >= 0) {
|
|
$this->order->updateItem($IDitem, intval($piece));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// order_discounts gifts
|
|
// TODO: Tohle budeme moci vyhodit, jakmile se začnou obecně ukládat na PurchaseState data z `$data['handled']` - Action Handlerů.
|
|
$actionHandlersData = getVal('action_handler');
|
|
$charges = null;
|
|
if (!$actionHandlersData) {
|
|
if ($gift = $this->order->getPurchaseState()->getCustomData('gift')) {
|
|
$qb = sqlQueryBuilder()->select('id, id_order_discount')->from('order_discounts_actions')
|
|
->where(Operator::inIntArray(array_keys($gift), 'id_order_discount'))
|
|
->andWhere(Operator::equals(['type' => 'gift']))->execute();
|
|
$gift_actions = sqlFetchAll($qb, ['id' => 'id_order_discount']);
|
|
foreach ($gift_actions as $id_action => $id_order_discount) {
|
|
$data = array_pop($gift[$id_order_discount]);
|
|
if ($data['selected']) {
|
|
if (empty($data['id_variation'])) {
|
|
$data = ['gift' => $data['id_product']];
|
|
} else {
|
|
$data['gift'] = $data['id_variation'];
|
|
}
|
|
}
|
|
$actionHandlersData[$id_action] = $data;
|
|
}
|
|
}
|
|
$charges = array_filter($this->order->fetchItems(),
|
|
fn ($item) => (($item['note']['item_type'] ?? null) == 'orders_charge') && !empty($item['note']['id_charge']));
|
|
$charges = Mapping::mapKeys($charges, fn ($k, $item) => [$item['note']['id_charge'], $item]);
|
|
}
|
|
|
|
$this->discountManager->setPurchaseState($this->order->getPurchaseState());
|
|
if ($actionHandlersData) {
|
|
$this->discountManager->setActionHandlersData($actionHandlersData);
|
|
}
|
|
$purchaseState = $this->discountManager->recalculate();
|
|
if ($handlers = $this->discountManager->getActionHandlers()) {
|
|
$purchaseState->setDiscountHandlers($handlers);
|
|
$ordersChargesHandlers = array_filter($handlers, function ($handler) {
|
|
return $handler instanceof OrdersChargesHandler;
|
|
});
|
|
if ($ordersChargesHandlers && $charges) {
|
|
foreach ($ordersChargesHandlers as $handler) {
|
|
$id_discount = $handler->getOrderDiscount()?->getId();
|
|
if ($id_discount && in_array($id_discount, $purchaseState->getUsedDiscounts())) {
|
|
$vars = $handler->getVars();
|
|
$id_charge = $vars['data']['id_charge'] ?? null;
|
|
if ($id_charge && array_key_exists($id_charge, $charges)) {
|
|
$data = ['checked' => 'Y'];
|
|
$handler->handleData($data);
|
|
$actionHandlersData[$handler->getActionId()] = $data;
|
|
$this->discountManager->setActionHandlersData($actionHandlersData);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
$this->order->total_price = $purchaseState->getTotalPrice()->getPriceWithVat();
|
|
$this->order->total_price_without_vat = $purchaseState->getTotalPrice()->getPriceWithoutVat();
|
|
|
|
if (in_array($this->getAcn(), ['recount', 'deleteItem', 'send', 'addCart'])) {
|
|
// Check for products not on stock
|
|
$failedProducts = $this->checkProductsInStore();
|
|
$pageVars['failedProducts'] = $failedProducts;
|
|
// Check for delivery exception
|
|
try {
|
|
$this->recalculateDelivery();
|
|
} catch (\Exception $e) {
|
|
$pageVars['failedDelivery'] = $e->getMessage();
|
|
}
|
|
|
|
if (empty($failedProducts) && empty($pageVars['failedDelivery'])) {
|
|
// send
|
|
if ($this->getAcn() == 'send') {
|
|
sqlGetConnection()->transactional(function () {
|
|
$this->order->setPurchaseState(null);
|
|
$this->discountManager->setPurchaseState($this->order->getPurchaseState());
|
|
$purchaseState = $this->discountManager->recalculate();
|
|
// Musím vynulovat IDčka položek, protože by se pak míchaly dohromady IDčka order_item a order_edit tabulek
|
|
foreach ($purchaseState->getPurchaseItems() as $purchaseItem) {
|
|
$purchaseItem->setId(null);
|
|
}
|
|
|
|
$this->purchaseUtil->createOrderFromPurchaseState($purchaseState, $this->order->id);
|
|
|
|
if ($gift = $this->order->getPurchaseState()->getCustomData('gift')) {
|
|
$discountsData = $this->order->getData('discounts');
|
|
$discountsData['gift'] = $gift;
|
|
$this->order->setData('discounts', $discountsData);
|
|
}
|
|
|
|
// Clean edit items
|
|
sqlQuery('DELETE FROM order_edit WHERE id_order=:id_order', ['id_order' => $this->orderId]);
|
|
|
|
$this->order->changeStatus(0, 'Uživatel editoval objednávku', false);
|
|
|
|
$this->sendOrderEvent($this->order, OrderEvent::USER_EDITED);
|
|
});
|
|
}
|
|
|
|
if (!isAjax()) {
|
|
throw new RedirectException(
|
|
createScriptURL([
|
|
'URL' => 'launch.php',
|
|
's' => 'orderView',
|
|
'IDo' => $this->orderId,
|
|
'edit' => $this->getAcn() != 'send',
|
|
'cf' => $this->request->get('cf'),
|
|
])
|
|
);
|
|
}
|
|
}
|
|
} else {
|
|
// Check for products not on stock
|
|
$failedProducts = $this->checkProductsInStore();
|
|
$pageVars['failedProducts'] = $failedProducts;
|
|
// Check for delivery exception
|
|
try {
|
|
$this->recalculateDelivery();
|
|
} catch (\Exception $e) {
|
|
$pageVars['failedDelivery'] = $e->getMessage();
|
|
}
|
|
}
|
|
|
|
if ($this->getAcn() == 'storno') {
|
|
$this->storno();
|
|
}
|
|
|
|
if ($this->getAcn() == 'cancel') {
|
|
$this->cancel();
|
|
}
|
|
|
|
$this->order->fetchItems();
|
|
$this->order->fetchItemsPhoto();
|
|
|
|
return $pageVars;
|
|
}
|
|
|
|
public function sendOrderEvent($order, $eventName)
|
|
{
|
|
$event = new OrderEvent($order);
|
|
$this->eventDispatcher->dispatch($event, $eventName);
|
|
|
|
return $event;
|
|
}
|
|
|
|
/**
|
|
* @throws RedirectException
|
|
*/
|
|
private function cancel()
|
|
{
|
|
sqlQuery('DELETE FROM '.getTableName('order_edit')." WHERE id_order='{$this->orderId}'");
|
|
|
|
throw new RedirectException(
|
|
createScriptURL([
|
|
'URL' => 'launch.php',
|
|
's' => 'orderView',
|
|
'IDo' => $this->orderId,
|
|
'cf' => $this->request->get('cf'),
|
|
])
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @throws RedirectException
|
|
*/
|
|
protected function storno()
|
|
{
|
|
$this->order->setEditMode(false);
|
|
$this->order->storno();
|
|
|
|
throw new RedirectException(
|
|
createScriptURL([
|
|
'URL' => 'launch.php',
|
|
's' => 'orderView',
|
|
'IDo' => $this->orderId,
|
|
'cf' => $this->request->get('cf'),
|
|
])
|
|
);
|
|
}
|
|
|
|
protected function checkProductsInStore()
|
|
{
|
|
if (\Settings::getDefault()->order_availability !== \Settings::ORDER_AVAILABILITY_ALL) {
|
|
$qb = sqlQueryBuilder();
|
|
$qb->select('p.id, pv.id as id_variation, p.title, pv.title AS variation_title')
|
|
->from('order_edit', 'c')
|
|
->leftJoin('c', 'order_items', 'oi', "oi.id_order IS NULL OR (oi.id_order = {$this->orderId}
|
|
AND (c.id_product = oi.id_product AND ((c.id_variation IS NULL AND oi.id_variation IS NULL) OR c.id_variation = oi.id_variation)))")
|
|
->leftJoin('c', 'products', 'p', 'c.id_product = p.id')
|
|
->leftJoin('c', 'products_variations', 'pv', 'c.id_variation=pv.id')
|
|
->where('p.id IS NOT NULL')
|
|
->andWhere(\Query\Operator::equals(['c.id_order' => $this->orderId]))
|
|
->andWhere(\Query\Product::getProductInStock($qb).' < (c.pieces - IFNULL(oi.pieces, 0))');
|
|
|
|
if (findModule(\Modules::PRODUCTS, 'order_not_in_store')) {
|
|
$qb->andWhere(\Query\Operator::not('FIND_IN_SET("PR", p.campaign)'));
|
|
}
|
|
|
|
$failedProducts = sqlFetchAll($qb, 'id');
|
|
|
|
return $failedProducts;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* @throws RedirectException
|
|
*/
|
|
private function addCart()
|
|
{
|
|
// projit kosik
|
|
$where = ($this->user) ? ['id_user' => $this->user->id] : ['user_key' => \Cart::getCartID()];
|
|
|
|
sqlStartTransaction();
|
|
|
|
$SQL_cart = sqlQueryBuilder()->select('pieces, id_variation, id_product, note')
|
|
->from('cart')->where(\Query\Operator::equals($where))
|
|
->orderBy('date', 'DESC')->execute();
|
|
|
|
foreach ($SQL_cart as $row) {
|
|
$this->order->insertItem($row['id_product'], $row['id_variation'], $row['pieces'], $row['note']);
|
|
}
|
|
|
|
// Clean shopping cart
|
|
sqlQueryBuilder()->delete('cart')->where(\Query\Operator::equals($where))->execute();
|
|
|
|
sqlFinishTransaction();
|
|
|
|
if (findModule(\Modules::JS_SHOP)) {
|
|
$this->session->set(JsShopRefreshListener::SESSION_NAME, true);
|
|
}
|
|
|
|
$this->cart->invalidatePurchaseState();
|
|
}
|
|
|
|
private function deleteItem()
|
|
{
|
|
$IDitem = intval(getVal('IDi'));
|
|
$this->order->deleteItem($IDitem);
|
|
}
|
|
|
|
private function getPieces()
|
|
{
|
|
return getVal('pieces', null, []);
|
|
}
|
|
|
|
private function getAcn()
|
|
{
|
|
return getVal('acn', null, getVal('act'));
|
|
}
|
|
|
|
private function checkUser()
|
|
{
|
|
if ($this->user) {
|
|
$SQL = sqlQuery('SELECT id
|
|
FROM '.getTableName('orders')."
|
|
WHERE id='".$this->orderId."' AND id_user='".$this->user->id."'
|
|
LIMIT 1");
|
|
if (sqlNumRows($SQL) == 0) {
|
|
redirection('INDEX');
|
|
}
|
|
|
|
sqlFreeResult($SQL);
|
|
} else {
|
|
$cf = $this->request->get('cf');
|
|
if ($cf === null) {
|
|
redirection('LOGIN');
|
|
}
|
|
|
|
$qb = sqlQueryBuilder()
|
|
->select('id')
|
|
->from('orders')
|
|
->where('id=:IDo')
|
|
->setMaxResults(1)
|
|
->setParameter('IDo', $this->orderId)
|
|
->execute();
|
|
|
|
$code = null;
|
|
if ($qb->rowCount() == 1) {
|
|
$order = new \Order($this->orderId);
|
|
$code = $order->getSecurityCode();
|
|
}
|
|
|
|
if ($code != $cf || $qb->rowCount() == 0) {
|
|
throw new RedirectException(
|
|
createScriptURL([
|
|
'URL' => 'launch.php',
|
|
's' => 'orderView',
|
|
'IDo' => $this->orderId,
|
|
'cf' => $cf,
|
|
])
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @return $this
|
|
*/
|
|
public function setOrderId($orderId)
|
|
{
|
|
$this->orderId = intval($orderId);
|
|
|
|
return $this;
|
|
}
|
|
|
|
#[Required]
|
|
public function setDiscountManager(?DiscountManager $discountManager = null): void
|
|
{
|
|
$this->discountManager = $discountManager;
|
|
}
|
|
}
|