282 lines
9.8 KiB
PHP
282 lines
9.8 KiB
PHP
<?php
|
|
|
|
namespace KupShop\CheckAppBundle\Util;
|
|
|
|
use KupShop\BalikonosBundle\Balikobot;
|
|
use KupShop\CheckAppBundle\Exception\OrderCheckException;
|
|
use KupShop\KupShopBundle\Config;
|
|
use Query\Operator;
|
|
|
|
class OrderCheckoutWorker
|
|
{
|
|
/** @var Balikobot */
|
|
protected $balikobot;
|
|
|
|
/**
|
|
* @required
|
|
*/
|
|
public function setBalikobot(?Balikobot $balikobot): void
|
|
{
|
|
$this->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. <a href=\"#\" onclick=\"window.scanner.print('{$url}'); return false;\">Znovu vytisknout</a>";
|
|
}
|
|
}
|
|
|
|
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 <a href=\"javascript:nw('order', {$order->id})\">{$order->id}</a> 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;
|
|
}
|
|
}
|