getID(); $acn = $this->getAction(); $this->contextManager = ServiceContainer::getService(\KupShop\KupShopBundle\Context\ContextManager::class); $pageVars = getVal('body', $vars); $pageVars['data']['total_price'] = toDecimal($pageVars['data']['total_price'] ?? 0); if (!isset($Submit)) { if ($acn == 'add') { $pageVars['data']['status'] = 0; $pageVars['data']['date_created'] = date('Y-m-d H:i:s'); $pageVars['data']['status_payed'] = 0; $pageVars['data']['status_dispatch'] = 0; $pageVars['data']['status_storno'] = 0; } } $currencyContext = ServiceContainer::getService(CurrencyContext::class); $order = new Order($ID); if (!$order->createFromDB($ID)) { // Set default contexts when order does not exists $order->currency = $currencyContext->getDefaultId(); $order->id_language = ServiceContainer::getService(LanguageContext::class)->getDefaultId(); $order->delivery_country = ServiceContainer::getService(CountryContext::class)->getActiveId(); } $currencyContext->activate($order->currency ?? $currencyContext->getDefaultId()); $pageVars['data']['domain'] = $this->contextManager->activateOrder($order, function () { return Contexts::get(DomainContext::class)->getActiveWithScheme(); }); $pageVars['data']['complete_order'] = true; if (!empty($ID)) { $pageVars['data']['total_price_without_vat'] = toDecimal('0'); $qb = sqlQueryBuilder() ->select('oi.id, oi.id_product, oi.id_variation, oi.pieces, oi.piece_price, oi.total_price, oi.descr, oi.tax, oi.note as item_note, oi.discount, COALESCE(pv.in_store, p.in_store) in_store, COALESCE(pv.ean, p.ean) ean') ->from('order_items', 'oi') ->leftJoin('oi', 'products', 'p', 'p.id=oi.id_product') ->leftJoin('p', 'products_variations', 'pv', 'pv.id=oi.id_variation') ->where(\Query\Operator::equals(['oi.id_order' => $ID])) ->orderBySql($this->getItemsOrdering()); if (findModule(Modules::PRODUCTS_VARIATIONS, Modules::SUB_CODE)) { $qb->addSelect('COALESCE(pv.code, p.code) code'); } else { $qb->addSelect('p.code code'); } if (findModule(Modules::PRODUCTS, Modules::SUB_NOTE)) { $qb->addSelect('COALESCE(pv.note, p.note) note_'); } else { $qb->addSelect('\'\' as note_'); } if (findModule(Modules::STORES)) { $qb->andWhere(\KupShop\StoresBundle\Query\StoresQuery::addStoresInStoreAmounts()); $qb->groupBy('oi.id'); } if (findModule(Modules::PRODUCTS, Modules::SUB_PRICE_BUY)) { $qb->addSelect('oi.price_buy price_buy'); } $oop = []; foreach ($qb->execute() as $key => $item) { $product = new Product($item['id_product']); $item['ID'] = $item['id']; $item['discount'] = toDecimal($item['discount']); $item['Price'] = formatPrice($item['total_price'], $item['tax']); $item['PiecePrice'] = formatPrice($item['piece_price'], $item['tax']); $item['pieces'] = floatval($item['pieces']); $item['in_store'] = floatval($item['in_store']); $pageVars['data']['total_price_without_vat'] = $pageVars['data']['total_price_without_vat']->add(toDecimal($item['total_price'])); if (!empty($item['item_note'])) { $item['custom_data'] = $product->parseNote($item['item_note']); $item['item_note'] = $product->printNote($product->parseNote($item['item_note'])); } if ($item['in_store'] < 0) { if ($item['id_product']) { // Currently ordered offset $query = 'SELECT SUM(oi.pieces) FROM '.getTableName('order_items').' oi LEFT JOIN '.getTableName('orders').' o ON oi.id_order=o.id, '.getTableName('orders')." o2 WHERE o2.id={$ID} AND o.date_created >= o2.date_created AND oi.id_product={$item['id_product']} AND o.status_storno=0 AND o.id!={$ID} AND o.status IN (".join(',', getStatuses('active')).')'; if (!empty($item['id_variation'])) { $query .= "AND oi.id_variation={$item['id_variation']}"; } $item['piecesOrdered'] = returnSQLResult($query); if (($item['piecesOrdered'] + $item['in_store']) < 0) { $pageVars['data']['complete_order'] = false; } // Suppliers products if (findModule('products_suppliers')) { $query = 'SELECT SUM(in_store) FROM '.getTableName('products_of_suppliers')." pos WHERE pos.id_product={$item['id_product']}"; if (!empty($item['id_variation'])) { $query .= " AND pos.id_variation={$item['id_variation']}"; } $item['piecesInSuppliers'] = returnSQLResult($query); } } } if (!empty($item['id_product']) && empty($item['id_variation']) && $product->hasVariations()) { $item['class'] = 'row-red'; $item['variation_title'] = '!Neexistujici varianta!'; } $item['img'] = createScriptURL([ 's' => 'redir', 'type' => 'productImage', 'id' => $item['id_product'], 'id_variation' => $item['id_variation'], ]); if ($item['id_product'] && (findModule(Modules::PRODUCTS_SUPPLIERS) || findModule(Modules::ORDERS_OF_SUPPLIERS))) { $query = 'SELECT pos.in_store, pos.code, s.order_url, s.name, pos.price_buy, v.vat FROM '.getTableName('products_of_suppliers').' pos LEFT JOIN '.getTableName('suppliers').' s ON pos.id_supplier = s.id LEFT JOIN '.getTableName('products').' AS p ON pos.id_product=p.id LEFT JOIN '.getTableName('vats')." AS v ON v.id=p.vat WHERE pos.id_product={$item['id_product']}"; if (!empty($item['id_variation'])) { $query .= " AND pos.id_variation={$item['id_variation']}"; } $query .= ' ORDER BY s.id'; $item['suppliers'] = []; foreach (sqlQuery($query) as $supplier) { $item['suppliers'][] = $supplier; } } if (findModule(Modules::STOCK_IN)) { $sql = sqlQuery("SELECT sii.quantity as future_stock_in_pieces, sii.id_product, sii.id_variation, si.date_issued, s.name FROM stock_in_items sii JOIN stock_in si ON si.id = sii.id_stock_in AND si.id_index ='future' LEFT JOIN suppliers s ON si.id_supplier=s.id WHERE sii.id_product=:id_product AND ((sii.id_variation IS NULL AND :id_variation IS NULL) OR sii.id_variation=:id_variation)", ['id_product' => $item['id_product'], 'id_variation' => $item['id_variation']]); foreach (sqlFetchAll($sql) as $stock_in) { $diff = null; if ($stock_in['date_issued']) { $dateIssued = DateTime::createFromFormat('Y-m-d', $stock_in['date_issued']); $diff = (new DateTime())->diff($dateIssued); $diff = (int) $diff->format('%r%a'); } $item['stock_in'][] = [ 'future_stock_in_pieces' => $stock_in['future_stock_in_pieces'], 'date_issued' => $stock_in['date_issued'], 'name' => $stock_in['name'], 'stock_in_days' => $diff, ]; } $sql = sqlQuery("SELECT sii.quantity as preorder_stock_in_pieces, sii.id_product, sii.id_variation, si.date_issued, s.name FROM stock_in_items sii JOIN stock_in si ON si.id = sii.id_stock_in AND si.id_index ='preorder' LEFT JOIN suppliers s ON si.id_supplier=s.id WHERE sii.id_product=:id_product AND ((sii.id_variation IS NULL AND :id_variation IS NULL) OR sii.id_variation=:id_variation)", ['id_product' => $item['id_product'], 'id_variation' => $item['id_variation']]); foreach (sqlFetchAll($sql) as $stock_in) { $diff = null; if ($stock_in['date_issued']) { $dateIssued = DateTime::createFromFormat('Y-m-d', $stock_in['date_issued']); $diff = (new DateTime())->diff($dateIssued); $diff = (int) $diff->format('%r%a'); } $item['preorder_stock_in'][] = [ 'preorder_stock_in_pieces' => $stock_in['preorder_stock_in_pieces'], 'date_issued' => $stock_in['date_issued'], 'name' => $stock_in['name'], 'stock_in_days' => $diff, ]; } } $oop[$key] = $item; } $pageVars['oop'] = $oop; if (findModule('order_payment')) { $pageVars['paid'] = toDecimal($order->getPayments()); } if (!empty($pageVars['data']['invoice_email'])) { $pageVars['multipleOrder'] = returnSQLResult('SELECT o.id FROM orders o WHERE o.id!=:id AND o.status IN (:statuses) AND o.invoice_email=:email', ['id' => $ID, 'statuses' => getStatuses('active'), 'email' => $pageVars['data']['invoice_email']], ['statuses' => \Doctrine\DBAL\Connection::PARAM_INT_ARRAY]); } $SQL = sqlQuery("SELECT oh.id_status, oh.comment, oh.notified, a.login, DATE_FORMAT(oh.date, '{$GLOBALS['dbcfg']['date_format']} {$GLOBALS['dbcfg']['time_format']}') as datef, custom_data FROM ".getTableName('orders_history').' oh LEFT JOIN'.getTableName('admins')." a ON oh.admin=a.id WHERE oh.id_order='".$ID."' ORDER BY oh.date ASC"); $pageVars['orders_history'] = sqlFetchAll($SQL); $attachmentLocator = ServiceContainer::getService(AttachmentLocator::class); foreach ($pageVars['orders_history'] as &$history) { $sentAttachments = []; if (!empty($history['custom_data'])) { $customData = json_decode($history['custom_data'], true); $history['custom_data'] = $customData; if (isset($customData['initiator'])) { $history['custom_data']['initiator'] = Initiator::from($customData['initiator']); } if (!empty($customData['attachments'])) { foreach ($customData['attachments'] as $type) { $sentAttachments[] = $attachmentLocator->getAttachments(EmailGroupTypeEnum::ORDER)[$type]; } } $history['attachments'] = join(', ', $sentAttachments); } } $pageVars['attachments_types'] = json_encode($attachmentLocator->getAttachments(EmailGroupTypeEnum::ORDER)); $pageVars['attachments_urls'] = []; if ($this->getID()) { foreach ($attachmentLocator->getAttachments(EmailGroupTypeEnum::ORDER) as $type => $name) { $pageVars['attachments_urls'][$type] = path('kupshop_admin_emailattachment_adminattachment', ['id_order' => $this->getID(), 'type' => $type]); } } $pageVars['attachments_urls'] = json_encode($pageVars['attachments_urls']); // User price level if (findModule(Modules::PRICE_LEVELS)) { if ($orderPriceLevel = $order->getOrderPriceLevel()) { $pageVars['price_level'] = \KupShop\KupShopBundle\Wrapper\PriceLevelWrapper::wrap($orderPriceLevel); } } $orderInfo = ServiceContainer::getService(OrderInfo::class); $used_order_discounts = $orderInfo->getUsedDiscounts($order->id); $pageVars['data']['used_order_discounts'] = $used_order_discounts; $pageVars['data']['packages'] = $orderInfo->getPackages($order); } $pageVars['printSetOffer'] = [ 'common' => [ 'Prodejka' => 'Prodejky', ], 'products' => [ 'product' => 'Štítky produktů', ], ]; $pageVars['userInfo'] = $order->getUser(); if (!$pageVars['userInfo']) { $pageVars['userInfo'] = $this->selectSQL('users', ['email' => $order->getUserEmail()], ['id', 'note'])->fetch(); } if ($order) { $pageVars['custom_data'] = $order->getDataAll(); } $pageVars['delivery_editable'] = true; if ($deliveryType = $order->getDeliveryType()) { $pageVars['delivery_editable'] = $deliveryType->getDelivery()->requiresDeliveryAddress(); if (($payment = $deliveryType->getPayment()) && $payment->getSelectedMethodId()) { $contextManager = ServiceContainer::getService(ContextManager::class); $pageVars['payment_method'] = $contextManager->activateOrder($order, function () use ($payment) { $payment->loadConfig(Contexts::get(LanguageContext::class)->getActiveId()); return $payment->getSelectedMethod(); }); } } $pageVars['data']['flags_array'] = explodeFlags($pageVars['data']['flags']); /** @var SMSSender $smsSender */ $smsSender = ServiceContainer::getService(SMSSender::class); $pageVars['SMSSenderBackend'] = $smsSender->getBackend(); return array_merge($vars, [ 'type' => 'orders', 'body' => $pageVars, 'order' => $order, ]); } public function getPrintAttachments() { $order = $this->prepareOrder(); $attachments = []; $attachmentLocator = ServiceContainer::getService(AttachmentLocator::class); foreach ($attachmentLocator->getAttachments(EmailGroupTypeEnum::ORDER) as $type => $name) { if (($type == 'order_invoice') && findModule(Modules::ORDERS, Modules::SUB_INVOICES_FORBIDDEN)) { continue; } $attachments[$type] = $name; } return $attachments; } public function getData() { global $cfg, $dbcfg; $data = parent::getData(); $acn = $this->getAction(); $ID = $this->getID(); // kontrola hodnot if (isset($data['date_created']) && empty($data['date_created'])) { $data['date_created'] = date('d-m-Y H:i:s'); } if (isset($data['status']) && !is_numeric($data['status'])) { $data['status'] = 0; } if (isset($data['status_payed'])) { $this->prepareBoolean($data['status_payed']); } if (isset($data['status_dispatch']) && !is_numeric($data['status_dispatch'])) { $data['status_dispatch'] = 0; } if (isset($data['status_storno']) && !is_numeric($data['status_storno'])) { $data['status_storno'] = 0; } if (isset($data['id_user']) && intval($data['id_user']) <= 0) { $data['id_user'] = null; } if (!empty($data['date_created'])) { $data['date_created'] = $this->prepareDateTime($data['date_created']); } if (!empty($data['date_handle'])) { $data['date_handle'] = $this->prepareDateTime($data['date_handle']); } if (!empty($data['date_delivered'])) { $data['date_delivered'] = $this->prepareDateTime($data['date_delivered']); } if (!empty($data['date_accept'])) { $data['date_accept'] = $this->prepareDateTime($data['date_accept']); } if (!empty($data['date_due'])) { $data['date_due'] = $this->prepareDateTime($data['date_due']); } if (!empty($cfg['Order']['Flags'])) { $flags = getVal('flags', $data, []); $flags = join(',', $flags); $data['flags'] = $flags; } if (!empty($data['tab_selected'])) { if ($data['tab_selected'] === 'retail') { $data['invoice_name'] = translate('retailSale', 'orders', false, true); } } if (!empty($data['id_user']) && (empty($data['invoice_name']) && empty($data['invoice_email']))) { $this->injectUserData($data); } $delivers_fields = [ 'delivery_name' => 'invoice_name', 'delivery_surname' => 'invoice_surname', 'delivery_firm' => 'invoice_firm', 'delivery_street' => 'invoice_street', 'delivery_city' => 'invoice_city', 'delivery_zip' => 'invoice_zip', 'delivery_country' => 'invoice_country', 'delivery_phone' => 'invoice_phone', ]; if (empty($data['delivery_name']) && empty($data['delivery_surname']) && empty($data['delivery_firm']) && empty($data['delivery_street']) && empty($data['delivery_city']) && empty($data['delivery_zip']) && empty($_GET['data']['invoice_name']) ) { foreach ($delivers_fields as $delivery_fieldname => $invoice_fieldname) { if (!empty($data[$invoice_fieldname])) { $data[$delivery_fieldname] = $data[$invoice_fieldname]; } } } // getData se volá víckrát, a potřebujeme zajistit že máme fakt původní objednávku vč. custom data if (!$this->oldOrder && $ID) { $this->oldOrder = new Order(); $this->oldOrder->createFromDB($ID); $this->oldOrder->getDataAll(); } if (!empty($data['delivery_data']) && $ID) { $order = new Order(); $order->createFromDB($ID); $delivery = $order->getDeliveryType()->getDelivery(); $pointData = $delivery->storeDeliveryInfo($data['delivery_data']); $order->setData('delivery_data', $pointData); try { $delivery->applyToOrder($data, $order); } catch (InvalidArgumentException $e) { $this->returnError($e->getMessage()); } } if (!empty($data['delivery']) && !empty($data['payment'])) { if ($deliveryTypeID = $this->selectSQL('delivery_type', ['id_delivery' => $data['delivery'], 'id_payment' => $data['payment']], ['id'])->fetchColumn()) { $deliveryType = DeliveryType::get($deliveryTypeID, true); $data['id_delivery'] = $deliveryTypeID; $data['delivery_type'] = $deliveryType->name; } } elseif (($data['delivery'] ?? false) === '0' && ($data['payment'] ?? false) === '0') { $data['id_delivery'] = null; $data['delivery_type'] = ''; } if (getVal('Submit') && $acn == 'add') { $data['order_no'] = '_999999'; // .rand(0, 999999); $currencyContext = ServiceContainer::getService(CurrencyContext::class); $allCurrencies = $currencyContext->getAll(); if (findModule('currencies') && isset($data['currency']) && isset($allCurrencies[$data['currency']])) { $data['currency_rate'] = $allCurrencies[$data['currency']]->getRate(); } $countryContext = Contexts::get(CountryContext::class); if (!$data['delivery_country']) { $data['delivery_country'] = $countryContext->getDefaultId(); } if (!$data['invoice_country']) { $data['invoice_country'] = $countryContext->getDefaultId(); } } return $data; } public function injectUserData(&$data) { $userFields = array_merge([ 'ico' => 'invoice_ico', 'dic' => 'invoice_dic', 'email' => 'invoice_email', 'currency' => 'currency', 'id_language' => 'id_language', ], Mapping::mapKeys(User::getFields(), function ($_, $x) { return [$x, "invoice_{$x}"]; }), Mapping::mapKeys(User::getFields(), function ($_, $x) { return ["delivery_{$x}", "delivery_{$x}"]; }) ); $user = sqlQueryBuilder() ->select('*') ->from('users') ->where(Operator::equals(['id' => $data['id_user']])) ->execute()->fetchAssociative(); if (!$user) { return false; } foreach ($user as $key => $field) { if (!empty($field) && isset($userFields[$key])) { $data[$userFields[$key]] = $field; } } if (!empty($user['prefer_transport']) && empty($data['delivery']) && empty($data['payment'])) { $deliveryType = DeliveryType::get($user['prefer_transport'], true); $data['delivery'] = $deliveryType->id_delivery; $data['payment'] = $deliveryType->id_payment; } return true; } public function handleUpdate() { $ID = $this->getID(); $acn = $this->getAction(); $data = $this->getData(); // kontrola jestli objednavka nebyla stornovana $storno = ReturnSQLResult('SELECT status_storno FROM '.getTableName('orders')." WHERE id='{$ID}'"); if (intval($storno) == 1 && !$this->isDuplicate()) { // Stornovanou objednávku již nelze upravovat $this->returnError(getTextString('orders', 'errorCanceledCantEdit')); } if ($this->isDuplicate()) { $OLD_ID = $ID; $data['order_no'] = ''; } $error = 0; if (empty($error)) { $order = new Order(); if ($acn == 'edit') { $order->createFromDB($ID); } $SQL = parent::handleUpdate(); if ($SQL) { if ($acn == 'add') { $ID = $this->getID(); // set date created sqlQueryBuilder() ->update('orders') ->set('date_created', 'NOW()') ->set('source', ':source') ->setParameter('source', OrderInfo::ORDER_SOURCE_ADMIN) ->where(Operator::equals(['id' => $ID])) ->execute(); $order->createFromDB($ID); if (!empty($data['id_invoice'])) { $order->setData('id_invoice', $data['id_invoice']); } // dispatch order created event - order no is generated in event subscriber $this->getEventDispatcher()->dispatch(new OrderEvent($order), OrderEvent::ORDER_CREATED); addActivityLog( ActivityLog::SEVERITY_NOTICE, ActivityLog::TYPE_CHANGE, sprintf(getTextString('orders', 'activityAdded'), $order->order_no) ); if ($this->isDuplicate()) { $old_order = new Order(); $old_order->createFromDB($OLD_ID); $manager = ServiceContainer::getService(ContextManager::class); $manager->activateOrder($order, function () use ($order, $old_order) { $fields = [ 'date_accept' => null, 'date_handle' => null, ]; if (findModule('currencies')) { $fields['currency'] = $old_order->currency; $fields['currency_rate'] = $old_order->currency_rate; } if (findModule(Modules::TRANSLATIONS)) { $fields['id_language'] = $old_order->id_language; } try { $order->copyItems($old_order, false, dispatchEvent: true); } catch (\Exception $e) { $this->addError($e->getMessage()); } $this->updateSQL('orders', $fields, ['id' => $order->id]); if ($deliveryData = $old_order->getData('delivery_data')) { $order->setData('delivery_data', $deliveryData); } if ($paymentData = $old_order->getData('payment_data')) { $order->setData('payment_data', $paymentData); } $event = new OrderEvent($order); $this->getEventDispatcher()->dispatch($event, OrderEvent::ORDER_COMPLETE); }); } $order->status = -1; } elseif ($acn == 'edit') { $event = new OrderEvent($order); $this->getEventDispatcher()->dispatch($event, OrderEvent::ORDER_EDITED); addActivityLog(ActivityLog::SEVERITY_NOTICE, ActivityLog::TYPE_CHANGE, sprintf(getTextString('orders', 'activityEdited'), $data['order_no']), data: ActivityLog::addObjectData([$order->id => $order->order_no], 'orders') ); if ($order->id_delivery != ($data['id_delivery'] ?? false) || ($this->oldOrder !== null && $this->oldOrder->getData('delivery_data', false) != $data['delivery_data'])) { $order->setData('delivery_data_old', $this->oldOrder->getData('delivery_data', false)); $event = new OrderEvent($order); $this->getEventDispatcher()->dispatch($event, OrderEvent::ORDER_DELIVERY_CHANGED); } } foreach ($data['custom_data'] ?? [] as $key => $value) { $order->setData($key, $value); } $smsService = ServiceContainer::getService(SMSSender::class); if ($smsService->getBackend() && !empty($data['send_telfa_sms'])) { if (empty($data['invoice_phone'])) { $this->returnError('Není vyplněno telefonní číslo příjemce sms!'); } if (empty($data['comments'])) { $this->returnError('Neodesláno - prázdná zpráva!'); } $order = new Order($ID); $order->createFromArray($data); $message = $order->replacePlaceholders($data['comments']); $res = $smsService->getBackend()->sendSMS($data['invoice_phone'], strip_tags($message)); if ($res !== true) { $this->returnError('SMS se nepodařilo odeslat'); } $smsService->saveSMStoOrder($ID, 'Na tel. '.$data['invoice_phone'].': '.$message, 2, $order->status); $this->returnOK('SMS odeslána.'); } // Custom data $this->saveCustomOrderData($data['data'] ?? []); // Change order status $force = null; $data['comments'] = trim($data['comments'] ?? ''); if ($data['comments'] != '') { $force = true; } if (!empty($data['doNotNotify']) || $acn == 'add') { $force = false; } $order->changeStatus($data['status'], $data['comments'], $force, $data['status_comment']); if ($this->getErrors()) { $this->returnError($this->getErrors()[0], true); } $this->returnOK(null, true); } else { $this->returnError($GLOBALS['txt_str']['status']['scripterror']); } } } public function saveCustomOrderData($data) { $order = $this->prepareOrder(); if (!empty($data)) { foreach ($data as $key => $value) { $order->setData($key, $value); } } } public function handleDelete() { $ID = $this->getID(); if (!findRight('ORDER')) { redirect('launch.php?s=error.php&id=1'); } try { sqlGetConnection()->transactional(function () use ($ID) { $SQL = sqlQuery( 'SELECT order_no FROM '.getTableName('orders')." WHERE id='".$ID."' " ); $order = sqlFetchArray($SQL); sqlFreeResult($SQL); writeDownActivity(sprintf(getTextString('orders', 'activityDeleted'), $order['order_no'])); $SQL = sqlQuery( 'SELECT id_product, id_variation, pieces FROM '.getTableName('order_items')." WHERE id_order='".$ID."' AND id_product<>0 " ); while (($row = sqlFetchArray($SQL)) !== false) { $prod = new Product($row['id_product']); $prod->sell($row['id_variation'], -$row['pieces']); } // ########################################################## // smazat polozky objednavky sqlQuery('DELETE FROM '.getTableName('order_items')." WHERE id_order='{$ID}' "); // smazat objednavku sqlQuery('DELETE FROM '.getTableName('orders')." WHERE id='{$ID}' "); return; }); redirect('launch.php?s=orders.php&acn=erased'); } catch (Exception $e) { if (strpos($e->getMessage(), 'return_items') !== false) { $this->returnError(translate('returnedItemsDeleteOrder')); } getRaven()->captureException($e); } } protected function getEventDispatcher(): EventDispatcherInterface { static $eventDispatcher; if (!$eventDispatcher) { $eventDispatcher = ServiceContainer::getService('event_dispatcher'); } return $eventDispatcher; } protected function sendToBalikobot() { $data = $this->getData(); $this->saveCustomOrderData($data['data'] ?? []); $balikobot = ServiceContainer::getService(\KupShop\BalikonosBundle\Balikobot::class); $order = $this->prepareOrder(); $data = $order->getData('balikobot'); try { if ($balikobot->hasMultipleCollectionPlaces() && !empty($data['user'])) { $balikobot->setCredentialsByName($data['user']); } $IDs[$this->getID()] = [ 'packages' => $data['packages'] ?? 1, 'note' => $data['note'] ?? null, 'size' => $data['size'] ?? null, ]; $balikobot->setIDs($IDs); $balikobot->sendDeliveries(); } catch (BalikonosException $e) { $this->returnError($e->getMessage()); } return $balikobot; } public function handlePrintTicket() { try { $balikobot = $this->sendToBalikobot(); if ($error = $balikobot->getError()) { $this->returnError($error); } else { $balikobot->printTickets(null, $this->getData()['data']['balikobot']['position'] ?? '1', '', [$this->getID()]); } } catch (BalikonosException $e) { $this->returnError($e->getMessage()); } } public function handlePrintExistingTicket() { try { $data = $this->getData(); $this->saveCustomOrderData($data['data'] ?? []); $balikobot = ServiceContainer::getService(\KupShop\BalikonosBundle\Balikobot::class); $balikobot->printTickets(null, $data['data']['balikobot']['position'] ?? '1', '', [$this->getID()]); } catch (BalikonosException $e) { $this->returnError($e->getMessage()); } } public function handleSendToBalikobot() { $balikobot = $this->sendToBalikobot(); if ($error = $balikobot->getError()) { $this->returnError($error); } else { $this->logBalikobotResult('Ručně nahráno do Balíkobota', $this->prepareOrder(), $balikobot); $this->returnOK('Úspěšně nahráno do Balíkobota'); } } public function handleDeleteFromBalikobot() { $balikobot = ServiceContainer::getService(\KupShop\BalikonosBundle\Balikobot::class); try { foreach ($this->getBalikobot() as $item) { if ($item['close'] != 2) { $balikobot->deletePackage($item['id'] ?? null); } } $this->logBalikobotResult('Ručně odebráno z Balíkobota', $this->prepareOrder(), $balikobot); $this->returnOK('Úspěšně odebráno z Balíkobota'); } catch (BalikonosException $e) { $this->returnError($e->getMessage()); } } private function logBalikobotResult(string $message, Order $order, KupShop\BalikonosBundle\Balikobot $balikobot): void { $error = $balikobot->getError(); if ($error) { $this->returnError($error); } $result = $balikobot->getResult(); $result = $result[0] ?? []; $id = $result['id_balikonos'] ?? ''; $packages = implode(', ', $result['package_ids'] ?? []); $packageCount = count($result['package_ids'] ?? []); $order->logHistory("{$message}. Balíky ({$packageCount}): {$packages}, ID: {$id}"); } public function getBalikobot() { return sqlQueryBuilder()->select('*')->from('balikonos') ->where(\Query\Operator::equals(['id_order' => $this->getID()])) ->orderBy('close', 'ASC') ->execute()->fetchAllAssociative(); } public function changeDelivery($id_delivery, $id_order = null) { $order = $this->prepareOrder($id_order); /** @var \KupShop\OrderingBundle\OrderDelivery $orderDelivery */ $orderDelivery = ServiceContainer::getService(\KupShop\OrderingBundle\OrderDelivery::class); try { $result = $orderDelivery->recalculateDelivery($order, $id_delivery); if ($result) { return true; } } catch (\KupShop\OrderingBundle\Exception\DeliveryException $e) { $this->returnError($e->getMessage()); } return false; } public function handleChangeCurrency() { sqlGetConnection()->transactional(function () { sqlQueryBuilder()->select('currency')->from('orders')->where(Operator::equals(['id' => $this->getID()]))->forUpdate()->execute(); $order = $this->prepareOrder(); $id_currency = getVal('id_currency'); if ($order->currency == $id_currency) { $this->returnOK('Ok', false); } $orderCurrencyConverter = ServiceContainer::getService(\KupShop\OrderingBundle\Util\Order\OrderCurrencyConverter::class); return $orderCurrencyConverter->changeOrderCurrency($order, $id_currency); }) ? $this->returnOK() : $this->returnOK('Nepodařilo se changeOrderCurrency.'); } public function handleMerge() { $ID = $this->getID(); $newID = getVal('id_merge'); if (empty($newID)) { $this->returnError('Nezadáno číslo objednávky'); } $order_old = $this->prepareOrder($ID); $order_new = $this->prepareOrder($newID); $this->mergeOrders($order_old, $order_new); $ErrStr = "Položky objednávky {$order_old->order_no} byly přesunuty do objednávky {$order_new->order_no}. Objednávka {$order_old->order_no} byla stornována."; $this->setID($newID); $this->returnOK($ErrStr); } /** * @param $order_old Order * @param $order_new Order * * @return bool */ public function mergeOrders($order_old, $order_new) { $ID = $order_old->id; $newID = $order_new->id; $event = new OrderMergeEvent($order_old, $order_new); $event_result = $this->getEventDispatcher()->dispatch($event, OrderMergeEvent::BEFORE_MERGE); if ($error = $event_result->getError()) { $this->returnError($error['message'] ?? 'Objednávky nelze sloučit!'); } $manager = ServiceContainer::getService(ContextManager::class); $manager->activateOrder($order_old, function () use ($newID, $ID) { $merged_items = sqlQueryBuilder()->select("GROUP_CONCAT(CONCAT('
', pieces, ' x ', descr)) as items")->from('order_items')->where(\Query\Operator::equals(['id_order' => $ID]))->execute()->fetch()['items']; sqlQueryBuilder()->update('order_items')->set('id_order', $newID)->where(\Query\Operator::equals(['id_order' => $ID]))->execute(); if (findModule(\Modules::ORDER_DISCOUNT)) { sqlQueryBuilder()->update('discounts_coupons')->set('id_order_used', $newID)->where(\Query\Operator::equals(['id_order_used' => $ID]))->execute(); sqlQueryBuilder()->update('discounts_coupons')->set('id_order_purchased', $newID)->where(\Query\Operator::equals(['id_order_purchased' => $ID]))->execute(); } if (findModule(Modules::EET)) { sqlQueryBuilder()->update('eet_sent_payment')->set('id_order', $newID)->where(\Query\Operator::equals(['id_order' => $ID]))->execute(); } $order_old = $this->prepareOrder($ID); $order_new = $this->prepareOrder($newID); // Stornuje se az niz, ale v ramci recalculate se zavola ORDER_PAID eventa a vygeneruje se faktura i pro tu nestornovanou, coz je blbe. $order_old->status_storno = 1; $order_old->recalculate(true); $order_new->recalculate(true); $payments = $order_old->getPaymentsArray(); foreach ($payments as $payment) { $order_new->updateSQL('order_payments', ['id_order' => $newID], ['id' => $payment['id']]); } $order_old->updatePayments(); $order_new->updatePayments(); $comment = sprintf(translate_shop('mergeSuccessComment', 'order_msg'), $order_new->order_no); $order_old->storno(false, null, false); // don't send ORDER_STORNO email (customerNotified = false) // send ORDER_COMMENT email $order_old->sendEmail($comment, null, false, \KupShop\KupShopBundle\Email\OrderEmail::getType()); // type=ORDER_COMMENT $comment = "Přidány položky objednávky {$order_old->order_no}:".$merged_items; $comment .= ".
Objednávka {$order_old->order_no} byla stornována."; $order_new->logHistory($comment, false); }); return true; } public function getDeliveryList() { $order = $this->prepareOrder(); if ($order->id !== null) { $contextManager = ServiceContainer::getService(ContextManager::class); return $contextManager->activateOrder($order, function () { return DeliveryType::getDeliveries(true); }); } return []; } public function getPaymentList() { $order = $this->prepareOrder(); if ($order->id !== null) { $contextManager = ServiceContainer::getService(ContextManager::class); return $contextManager->activateOrder($order, function () { return DeliveryType::getPayments(true); }); } return []; } public function getValidDeliveryTypes() { $deliveryTypes = DeliveryType::getAll(true); $return = []; $return['0-0'] = true; foreach ($deliveryTypes as $deliveryType) { $return[$deliveryType->id_delivery.'-'.$deliveryType->id_payment] = true; } return $return; } public function handleRefreshDeliveryType() { $data = $this->getData(); // save old delivery data to database - needed for correct delivery type/store change if ($this->oldOrder !== null && ($oldData = $this->oldOrder->getData('delivery_data', false))) { $this->oldOrder->setData('delivery_data_old', $oldData); } if (!empty($data['id_delivery'])) { $this->changeDelivery($data['id_delivery']); } $this->forceUpdate(); } public function getDeliveryTypeList($totalPrice) { $order = $this->prepareOrder(); if ($order->id !== null) { $contextManager = ServiceContainer::getService(ContextManager::class); return $contextManager->activateOrder( $order, function () use ($totalPrice) { return Order::getDeliveryTypeList($totalPrice, false, 0, true); } ); } return []; } public function handleSendMail() { $order = $this->prepareOrder(); if (in_array($order->status, getStatuses('handled'))) { $comment = sprintf(translate('commentSendInvoice', 'orders'), $order['order_no']); $log_comment = translate('activityInvoiceEmailSent', 'orders'); } else { $comment = sprintf(translate('commentSendRecap', 'orders'), $order['order_no']); $log_comment = translate('activityRecapEmailSent', 'orders'); } $order->logChange($log_comment, true); $order->sendEmail($comment, null, true, \KupShop\KupShopBundle\Email\OrderEmail::getType()); // type=ORDER_COMMENT $this->returnOK('Email odeslán'); } public function handleAddUserNote() { $order = $this->prepareOrder(); $note = getVal('note', null, ''); $userId = $order->id_user; if (empty($userId)) { $userId = $this->selectSQL('users', ['email' => $order->getUserEmail()], ['id'])->fetchColumn(); if (empty($userId)) { $userId = addUserEmail($order->getUserEmail()); } } if (empty($userId)) { throw new RuntimeException('Cannot add user note! $userId is empty'); } $this->updateSQL('users', ['note' => $note], ['id' => $userId]); $this->returnOK('K uživateli byla přidána poznámka.'); } public function prepareOrder($ID = null) { if (!$ID) { $ID = $this->getID(); } $order = new Order(); $order->createFromDB($ID); return $order; } public function handlePayOrder() { $order = $this->prepareOrder(); $contextManager = ServiceContainer::getService(ContextManager::class); $contextManager->activateOrder($order, function () use ($order) { $delivery_type = $order->getDeliveryType($order->getDeliveryId()); $pay_method = $delivery_type?->payment_class?->getPayMethod() ?: 0; $remaining_payment = $order->getRemainingPayment(); if (!$order->isActive()) { $this->returnOK('Stornována objednávka'); } if ($order->isPaid()) { $this->returnOK('Již zaplaceno'); } $title = 'Zaplaceno z administrace eshopu'; if ($remaining_payment < 0) { $title = 'Vrácení částky: objednávka '.$order->order_no; } $newId = $order->insertPayment($remaining_payment, $title, null, true, $pay_method); if (($remaining_payment < 0) && ($payment_class = $delivery_type->payment_class ?? null) && $payment_class->enabledReturnPayment()) { try { $payment_class->loadConfig($order->getLanguage()); $payment_class->setOrder($order); $result = $payment_class->returnPayment($remaining_payment, null, $newId); $message = translate('returnSucceed', 'orderPayment'); addActivityLog(ActivityLog::SEVERITY_SUCCESS, ActivityLog::TYPE_COMMUNICATION, $message, ['amount' => $remaining_payment, 'order_id' => $order->id, 'result' => $result]); $result['paymentClass'] = $payment_class->class; $result['session'] = ($result['id'] ?? '').'_'.$newId; $this->updateSQL('order_payments', ['payment_data' => json_encode($result)], ['id' => $newId]); $this->returnOK($message); } catch (PaymentException $e) { $this->deleteSQL('order_payments', ['id' => $newId]); if ($e->getShortMessage() == 'Adyen') { // the refund request was successfully received by Adyen - no result yet, // because you receive the outcome of the refund request asynchronously, in a REFUND webhook. addActivityLog(ActivityLog::SEVERITY_SUCCESS, ActivityLog::TYPE_COMMUNICATION, $e->getMessage(), ['amount' => $remaining_payment, 'order_id' => $order->id]); $this->returnOK($e->getMessage()); } $this->returnError($e->getMessage()); } } }); $this->returnOK(); } public function handleCopyUserData() { $order_data = $this->getData(); if (!empty($order_data['id_user'])) { $data = $this->getUserData($order_data['id_user']); if ($data) { $this->updateSQL('orders', $data, ['id' => $this->getID()]); } else { $this->returnError('Vyskytla se chyba.'); } } $this->returnOK('Aktualizováno'); } public function handleGenerateInvoiceNo() { if (!findRight('ORDER_INVOICE')) { redirect('launch.php?s=error.php&id=1'); } $order = $this->prepareOrder(); if (!$order->isActive()) { $this->returnError('Stornovaná objednávka'); } if ($invoice_no = $order->generateInvoiceNo()) { $order->logHistory("Ručně vygenována faktura {$invoice_no} k objednávce."); $this->returnOK('Objednávce vytvořena faktura '.$invoice_no); } } private function getUserData($id_user) { $SQL = $this->selectSQL('users', ['id' => $id_user])->fetchAll(); if (count($SQL) == 1) { $user = $SQL[0]; $fields = ['name' => 'invoice_name', 'id' => 'id_user', 'surname' => 'invoice_surname', 'firm' => 'invoice_firm', 'ico' => 'invoice_ico', 'dic' => 'invoice_dic', 'street' => 'invoice_street', 'city' => 'invoice_city', 'zip' => 'invoice_zip', 'country' => 'invoice_country', 'state' => 'invoice_state', 'custom_address' => 'invoice_custom_address', 'phone' => 'invoice_phone', 'email' => 'invoice_email', 'delivery_name' => 'delivery_name', 'delivery_surname' => 'delivery_surname', 'delivery_firm' => 'delivery_firm', 'delivery_street' => 'delivery_street', 'delivery_city' => 'delivery_city', 'delivery_zip' => 'delivery_zip', 'delivery_country' => 'delivery_country', 'delivery_state' => 'delivery_state', 'delivery_custom_address' => 'delivery_custom_address', 'delivery_phone' => 'delivery_phone', ]; $data = []; foreach ($user as $key => $field) { if (!empty($field) && isset($fields[$key])) { $data[$fields[$key]] = $field; } } return $data; } else { return false; } } public function getEmail() { /* @var OrderMessageEmail $email */ return ServiceContainer::getService(OrderMessageEmail::class); } public function hasRights($name = null) { switch ($name) { case Window::RIGHT_DELETE: return findRight('ORDER_ERASE'); default: return parent::hasRights($name); } } protected function getObject() { $object = parent::getObject(); // muze vyhodit NotFoundHttpException v pripade spatneho ID if (findRight('ORDERS_RESTRICTION') && $this->getID()) { $qb = sqlQueryBuilder() ->select('o.id') ->from('orders', 'o') ->where(Operator::equals(['o.id' => $this->getID()])); $ordersFilterSpec = ServiceContainer::getService(OrdersFilterSpecs::class); if ($specs = $ordersFilterSpec->getSpecs(getAdminUser()['data']['ordersRestrictionFilter'] ?? [])) { $qb->andWhere($specs); } // pokud se mi nepodari nacist objednavku, tak nemam prava na jeji zobrazeni a nebo neexistuje, tak hodim 404 if (!$qb->execute()->fetchOne()) { throw new AccessDeniedException(translate('orderNotFound', 'orders')); } } return $object; } public function getUserEmails(): UserMessagesInterface { return ServiceContainer::getService(OrderMessageEmail::class); } }