orderIDs = $orderIDs; } /** @required */ public function setMultiFetch(MultiFetch $multiFetch) { $this->multiFetch = $multiFetch; } /** @required */ public function setExcelGenerator(ExcelGenerator $excelGenerator) { $this->excelGenerator = $excelGenerator; } /** @required */ public function setOrderInfo(OrderInfo $orderInfo) { $this->orderInfo = $orderInfo; } protected function getFields() { if (!isset($this->fields)) { $this->fields = $this->prepareFields(); } return $this->fields; } protected function prepareFields() { $fields = [ 'order_no' => ['field' => 'o.order_no', 'name' => 'Kód'], 'status' => ['field' => 'o.status', 'name' => 'Stav objednávky'], 'status_payed' => ['field' => 'o.status_payed', 'name' => 'Zaplaceno'], 'status_storno' => ['field' => 'o.status_storno', 'name' => 'Stornováno'], 'date_created' => ['field' => 'o.date_created', 'name' => 'Datum objednávky', 'type' => 'datetime', 'format' => 'd.m.yyyy hh:mm:ss', 'width' => 16], 'date_accept' => ['field' => 'o.date_accept', 'name' => 'Datum přijetí', 'type' => 'datetime', 'format' => 'd.m.yyyy hh:mm:ss', 'width' => 16], 'date_handle' => ['field' => 'o.date_handle', 'name' => 'Datum vyřízení', 'type' => 'datetime', 'format' => 'd.m.yyyy hh:mm:ss', 'width' => 16], 'date_due' => ['field' => 'o.date_due', 'name' => 'Datum splatnosti', 'type' => 'datetime', 'format' => 'd.m.yyyy hh:mm:ss', 'width' => 16], 'source' => ['field' => 'o.source', 'name' => 'Zdroj objednávky'], 'items' => [ 'spec' => function (QueryBuilder $qb) { $qb->leftJoin('o', 'order_items', 'oi', 'oi.id_order = o.id'); return 'COUNT(oi.id) AS items'; }, 'name' => 'Počet položek', 'type' => DataType::TYPE_NUMERIC, ], 'total_price' => ['field' => 'o.total_price', 'name' => 'Cena s DPH', 'type' => DataType::TYPE_NUMERIC, 'format' => '0.00'], ]; if (findModule(\Modules::CURRENCIES)) { $fields['currency'] = ['field' => 'o.currency', 'name' => 'Měna']; $fields['id_language'] = ['field' => 'o.id_language', 'name' => 'Jazyk']; $fields['currency_rate'] = ['field' => 'o.currency_rate', 'name' => 'Kurz', 'type' => DataType::TYPE_NUMERIC, 'format' => '0.0000']; $dbcfg = \Settings::getDefault(); $fields['total_price_in_default_currency'] = ['field' => 'o.total_price*o.currency_rate AS total_price_in_default_currency', 'name' => 'Cena ('.$dbcfg['currency'].') s DPH', 'type' => DataType::TYPE_NUMERIC, 'format' => '0.00']; } foreach ($this->getVats() as $vatValue => $vatRow) { $fields["BASEVAT{$vatValue}"] = ['name' => 'Základ DPH '.$vatValue.'%', 'type' => DataType::TYPE_NUMERIC, 'format' => '0.00']; $fields["VAT{$vatValue}"] = ['name' => 'DPH '.$vatValue.'%', 'type' => DataType::TYPE_NUMERIC, 'format' => '0.00']; } $fields = array_merge($fields, [ 'invoice_name' => ['field' => 'o.invoice_name', 'name' => 'Jméno'], 'invoice_surname' => ['field' => 'o.invoice_surname', 'name' => 'Příjmení'], 'invoice_firm' => ['field' => 'o.invoice_firm', 'name' => 'Firma'], 'invoice_email' => ['field' => 'o.invoice_email', 'name' => 'Email'], 'invoice_phone' => ['field' => 'o.invoice_phone', 'name' => 'Telefon'], 'invoice_street' => ['field' => 'o.invoice_street', 'name' => 'Ulice'], 'invoice_city' => ['field' => 'o.invoice_city', 'name' => 'Město'], 'invoice_zip' => ['field' => 'o.invoice_zip', 'name' => 'PSČ'], 'invoice_country' => ['field' => 'o.invoice_country', 'name' => 'Země'], 'invoice_state' => ['field' => 'o.invoice_state', 'name' => 'Stát/region'], 'invoice_custom_address' => ['field' => 'o.invoice_custom_address', 'name' => 'Upřesnění adresy'], 'invoice_ico' => ['field' => 'o.invoice_ico', 'name' => 'IČO'], 'invoice_dic' => ['field' => 'o.invoice_dic', 'name' => 'DIČ'], 'delivery_name' => ['field' => 'o.delivery_name', 'name' => 'Doruč. jméno'], 'delivery_surname' => ['field' => 'o.delivery_surname', 'name' => 'Doruč. příjmení'], 'delivery_firm' => ['field' => 'o.delivery_firm', 'name' => 'Doruč. firma'], 'delivery_street' => ['field' => 'o.delivery_street', 'name' => 'Doruč. ulice'], 'delivery_city' => ['field' => 'o.delivery_city', 'name' => 'Doruč. město'], 'delivery_zip' => ['field' => 'o.delivery_zip', 'name' => 'Doruč. PSČ'], 'delivery_country' => ['field' => 'o.delivery_country', 'name' => 'Doruč. země'], 'delivery_state' => ['field' => 'o.delivery_state', 'name' => 'Doruč. stát/region'], 'delivery_custom_address' => ['field' => 'o.delivery_custom_address', 'name' => 'Doruč. upřesnění adresy'], 'note_user' => ['field' => 'o.note_user', 'name' => 'Pozn. pro obchodníka'], 'flags' => ['field' => 'o.flags', 'name' => 'Příznaky'], 'delivery' => [ 'spec' => function (QueryBuilder $qb) { $qb->leftJoin('o', 'delivery_type', 'dt', 'dt.id = o.id_delivery') ->leftJoin('dt', 'delivery_type_delivery', 'dtd', 'dtd.id = dt.id_delivery'); return 'dtd.name AS delivery'; }, 'name' => 'Doprava', ], 'payment' => [ 'spec' => function (QueryBuilder $qb) { $qb->leftJoin('o', 'delivery_type', 'dt', 'dt.id = o.id_delivery') ->leftJoin('dt', 'delivery_type_payment', 'dtp', 'dtp.id = dt.id_payment'); return 'dtp.name AS payment'; }, 'name' => 'Platba', ], 'discounts' => ['name' => 'Použité slevy'], 'package_id' => ['field' => 'o.package_id', 'name' => 'Číslo balíku'], 'note_invoice' => ['field' => 'o.note_invoice', 'name' => 'Poznámka na faktuře'], 'consents' => ['field' => 'JSON_KEYS(note_admin, "$.consents") as consents', 'name' => 'Consents'], ]); if (findModule(\Modules::PRODUCTS, \Modules::SUB_WEIGHT)) { $fields['weight'] = ['name' => 'Váha objednávky', 'type' => DataType::TYPE_NUMERIC, 'format' => '0.000']; } if (findModule(\Modules::PRODUCTS, \Modules::SUB_PRICE_BUY)) { $fields['items_price_buy'] = [ 'name' => 'Nákupní cena', 'spec' => function (QueryBuilder $qb) { $qb->leftJoin('oi', 'products', 'p', 'p.id = oi.id_product'); $qb->leftJoin('oi', 'products_variations', 'pv', 'pv.id = oi.id_variation'); return 'SUM(COALESCE(oi.price_buy * o.currency_rate, pv.price_buy, p.price_buy)*oi.pieces) AS items_price_buy'; }, 'type' => DataType::TYPE_NUMERIC, ]; } if (findModule(\Modules::INVOICES)) { $fields['invoice_no'] = [ 'name' => 'Číslo faktury', 'field' => 'o.invoice_no', ]; } $fields['user_order_no'] = ['field' => 'o.user_order_no', 'name' => 'Zákazníkovo číslo objednávky']; return $fields; } protected function getVats(): array { if (!isset($this->vats)) { $vatsSQL = sqlQuery('SELECT id, descr, vat, is_default FROM vats ORDER BY vat DESC '); $vats = []; foreach ($vatsSQL as $row) { $vats[(string) $row['vat']] = $row; } $this->vats = $vats; } return $this->vats; } protected function prepareQuery(): QueryBuilder { /** @var $qb QueryBuilder */ $qb = sqlQueryBuilder()->select('o.id') ->from('orders', 'o') ->andWhere(\Query\Operator::inIntArray($this->orderIDs, 'o.id')) ->groupBy('o.id') ->orderBy('o.id'); foreach ($this->getFields() as $key => $arr) { if (isset($arr['field'])) { $qb->addSelect($arr['field']); } if (isset($arr['spec'])) { $qb->addSelect($arr['spec']); } } return $qb; } protected function prepareRow($row, \Order $order): array { $row['status'] = getOrderStatus($row['status'])['name'] ?? ''; $row['total_price'] = number_format($row['total_price'], 2, '.', ''); foreach ($this->getVats() as $vatValue => $value) { if (!empty($order->vats[$vatValue])) { $vat = $order->vats[$vatValue]; if (findModule('currencies')) { $total_price_without_vat = $vat['total_price_without_vat']->mul(toDecimal($row['currency_rate'])); $total_price_with_vat = $vat['total_price_with_vat']->mul(toDecimal($row['currency_rate'])); $row["BASEVAT{$vatValue}"] = $total_price_without_vat->printFloatValue(2); $row["VAT{$vatValue}"] = $total_price_with_vat->sub($total_price_without_vat)->printFloatValue(2); } else { $row["BASEVAT{$vatValue}"] = $vat['total_price_without_vat']->printFloatValue(2); $row["VAT{$vatValue}"] = $vat['total_price_with_vat']->sub($vat['total_price_without_vat'])->printFloatValue(2); } } else { $row["BASEVAT{$vatValue}"] = number_format(0, 2); $row["VAT{$vatValue}"] = number_format(0, 2); } } $row['discounts'] = join(',', $this->orderInfo->getUsedDiscounts($order->id)); if (findModule(\Modules::PRODUCTS, \Modules::SUB_WEIGHT)) { $row['weight'] = $order->getTotalWeight(); } return $row; } protected function checkItemsCount() { $data = $this->prepareQuery()->execute(); $items_count = $data->rowCount(); if ($items_count >= $this->ORDERS_ITEMS_LIMIT) { throw new ExportException('Export se nepodařil, protože byl překročen limit '.$this->ORDERS_ITEMS_LIMIT.' položek'); } if ($items_count == 0) { throw new ExportException('Export se nepodařil, protože zadanému filtru neodpovídá žádná položka'); } set_time_limit(600); } protected function getData() { $data = $this->prepareQuery()->execute()->fetchAll(); $chunks = array_chunk($data, 1000, false); foreach ($chunks as $chunk) { $filter = array_map(function ($x) { return $x['id']; }, $chunk); $orderList = new OrderList($this->multiFetch); $orders = $orderList->andSpec( function (QueryBuilder $qb) use ($filter) { $qb->andWhere(Operator::inIntArray($filter, 'o.id')); } )->getOrders(); $this->multiFetch->fetchItems($orders); foreach ($chunk as $row) { if ($orders[$row['id']] != null) { $output = $this->prepareRow($row, $orders[$row['id']]); $ordered = []; foreach ($this->getFields() as $key => $value) { $ordered[$key] = $output[$key]; } yield $ordered; } } } } public function export() { ini_set('memory_limit', '2048M'); $this->checkItemsCount(); $filename = 'objednavky_'.date('Y-m-d_H-i').'.xlsx'; $this->excelGenerator->generateExcel($this->getFields(), $this->getData(), $filename); return; } }