balikobot = $balikobot; } /** * Proved povinný kontroly nad objednávkou před výstupní kontrolou. */ public function checkOrder(string $order_no, ?\Order &$order) { if (empty($order_no)) { return 'Načtete prosím objednávku.'; } try { $order = \Order::createFromDbOrderNo($order_no); } catch (\InvalidArgumentException $e) { return 'Neexistující objednávka.'; } if ($error = $this->generalOrderCheck($order)) { return $error; } if ($this->balikobot && ($error = $this->balikobotOrderCheck($order))) { return $error; } return null; } public function generalOrderCheck($order) { if (!$order->isActive()) { return 'Stornovaná objednávka.'; } $deliveryType = $order->getDeliveryType(); if (!$deliveryType->id) { return 'Neexistující způsob doručení.'; } if ($deliveryType->isInPerson() && $order->getData('checkout_control')) { return 'Výstupní kontrola proběhla! Připraveno na Osobní předání!'; } $items = $order->fetchItems(); $products = array_filter($items, function ($i) { return !empty($i['id_product']); }); if (!$products) { return 'Objednávka nemá produkty.'; } return null; } public function balikobotOrderCheck($order) { if ($this->balikobot->isDeliverySupported($order->getDeliveryType()->id_delivery)) { $balikobotRow = sqlQueryBuilder() ->select('id, close')->from('balikonos') ->where(Operator::equals(['id_order' => $order->id])) ->andWhere('close = 1') ->execute()->fetch(); if ($balikobotRow) { $url = Config::get()['Addr']['full']."admin/launch.php?s=orders.php&acn=edit&acn=PrintTicket&ID={$order->id}"; return "Štítek byl už jednou vytisknut. Znovu vytisknout"; } } return null; } public function getOrderCheckData(int $id_order) { $order = new \Order(); $order->createFromDB($id_order); // it means order does not exist if ($order->order_no === null) { return false; } $order->fetchItems(); $order->productList->fetchMainImages(3); $data = []; foreach ($order->fetchItems() as $item) { // TODO vyhazovat neproduktovy polozky? if ($item['id_product'] === null || $item['pieces'] <= 0) { continue; } $additionalData = $this->getAdditionalData($item['id_product'], $item['id_variation']); $variationCode = null; if (!empty($item['id_variation']) && findModule(\Modules::PRODUCTS_VARIATIONS, 'variationCode')) { $variationCode = sqlQueryBuilder()->select('code')->from('products_variations') ->where(Operator::equals(['id' => $item['id_variation']])) ->execute()->fetchColumn(); } $newData = [ 'id' => $item['id'], 'title' => $item['descr'], 'quantity' => (int) $item['pieces'], 'code' => !empty($variationCode) ? $variationCode : ($item['product']->code ?? ''), 'ean' => formatEAN($item['ean']), 'id_product' => $item['id_product'], 'id_variation' => $item['id_variation'], 'note' => $item['product']->note_ ?? '', 'serial_number_require' => $additionalData['serial_number_require'] ?? '', 'image' => $item['product']->image['src'] ?? '', 'positions' => $additionalData['positions'] ?? '', 'supplier_eans' => explode(';', $additionalData['supplier_eans'] ?? ''), 'supplier_codes' => explode(';', $additionalData['supplier_codes'] ?? ''), ]; $data[] = $newData; } // Srovnat aby ty bez EANů byly na konci usort($data, function ($a, $b) { return empty($b['ean']) <=> empty($a['ean']); }); $index = 0; foreach ($data as &$item) { $item['index'] = $index++; } return array_values($data); } protected function getAdditionalData($id_product, $id_variation) { $data = []; if (findModule(\Modules::PRODUCTS_SERIAL_NUMBERS)) { $serial_number_require = sqlQueryBuilder()->select('serial_number_require')->from('products') ->where(Operator::equals(['id' => $id_product])) ->execute()->fetchColumn(); $data['serial_number_require'] = $serial_number_require; } return $data; } /** * @return array */ public function checkoutOrder($order_no) { /** @var \Order $order */ if ($errors = $this->checkOrder($order_no, $order)) { return [ 'result' => false, 'message' => $errors, ]; } $deliveryType = $order->getDeliveryType(); if ($deliveryType->isInPerson()) { return $this->checkoutInPersonOrder($order); } if ($this->balikobot && $this->balikobot->isDeliverySupported($deliveryType->id_delivery)) { return $this->checkoutBalikobotOrder($order); } } public function checkoutInPersonOrder($order) { $order->setData('checkout_control', true); $order->logHistory('Proběhla výstupní kontrola. Připraveno na osobní odběr.'); return [ 'result' => true, 'message' => 'Připraveno na osobní odběr.', ]; } public function checkoutBalikobotOrder($order) { // Send data to Balikobot $balikobot = $this->sendToBalikobot($order); if ($balikobot_error = $balikobot->getError()) { return [ 'result' => false, 'message' => "Objednávku id})\">{$order->id} se nepodařilo odeslat o Balíkobota: {$balikobot_error}", ]; } $order->setData('checkout_control', true); $order->logHistory('Proběhla výstupní kontrola. Objednávka nahrána do Balíkobota.'); return [ 'result' => true, 'message' => 'Tiskneme etiketu.', 'printOrderLabel' => $order->id, ]; } public function checkoutOrderSerialNumbers($items) { $items = array_filter($items ?? [], function ($item) { return $item->serial_number_require === 'Y'; }); sqlGetConnection()->transactional( function () use ($items) { foreach ($items as $item) { if (count($item->serialNumbers) == $item->checked) { if (count($item->serialNumbers) > count(array_unique($item->serialNumbers))) { throw new OrderCheckException('Produkt s ID '.$item->id_product.' má duplicitní SN.'); } foreach ($item->serialNumbers as $serialNumber) { $selectedSN = sqlQueryBuilder()->select('psn.id', 'psn.id_order_item') ->from('products_serial_numbers', 'psn') ->where( Operator::equalsNullable( [ 'psn.serial_number' => $serialNumber, 'psn.id_product' => $item->id_product, 'psn.id_variation' => $item->id_variation, ] ) )->execute()->fetch(); if (!$selectedSN) { throw new OrderCheckException('Produkt s ID '.$item->id_product.' a SN "'.$serialNumber.'" není dostupný.'); } elseif (!empty($selectedSN['id_order_item']) && $selectedSN['id_order_item'] != $item->id) { throw new OrderCheckException('Produkt s ID '.$item->id_product.' a SN "'.$serialNumber.'" je už v jiné objednávce.'); } sqlQueryBuilder()->update('products_serial_numbers', 'psn') ->directValues(['id_order_item' => $item->id]) ->where(Operator::equals([ 'id' => $selectedSN['id'], ]))->execute(); } } else { throw new OrderCheckException('Produkt s id '.$item->id_product.' má méně SN než je nakliknuto.'); } } }); } protected function sendToBalikobot($order, $reclamation = null) { $data = $order->getData('balikobot'); $IDs[$order->id] = [ 'packages' => $data['packages'] ?? 1, 'note' => $data['note'] ?? null, ]; $this->balikobot->setIDs($IDs); $this->balikobot->sendDeliveries(); return $this->balikobot; } }