logger = $logger; $this->storeItemWorker = $storeItemWorker; } protected $inventoryPosition; /** * @param int $position * @param array $products * @param null $position_code * * @return array * * @throws \Throwable */ public function submitInventory($position, $products, $position_code = null) { $result = []; sqlGetConnection()->transactional(function () use ($position, $products, &$result, $position_code) { $inventoryDate = new \DateTime(); $inventoryDate->setTimezone(new \DateTimeZone(date_default_timezone_get())); foreach ($products as $product) { $ean = $product->ean; $batchId = $product->id_product_batch ?? null; $existsProductOnPosition = $this->storeItemWorker->checkProductByEanAndLocation($ean, null, $position_code, $batchId); // TODO: Tohle je desne pomaly a lockuje to veskery dalsi pohyby ve skladu i kosik / objednavky. // Mozna by stacilo selectit jen p.in_store a pv.in_store, aby se locknul jen ten jeden sloupecek, ale stejne to asi bude problem. // Zkusil jsem pridat indexy na EANy a porad to bylo pomaly :-( // Proc tohle nejde napsat pres id produktu? Ze by se to pustilo az za nasledujicim dotazem a uz jsme vedeli idcka // sqlQuery('SELECT * FROM products p // JOIN products_variations pv ON pv.id_product = p.id // LEFT JOIN products_of_suppliers pos ON p.id=pos.id_product AND (pv.id IS NULL OR pv.id=pos.id_variation) // WHERE pv.ean=:ean OR p.ean=:ean OR pos.ean=:ean FOR UPDATE', ['ean' => $ean]); if (!$existsProductOnPosition) { $eProdOnPosSQL = sqlQueryBuilder() ->select('p.id as id_product, pv.id as id_variation, 0 as pieces') ->from('products', 'p') ->joinVariationsOnProducts() ->leftJoin('pv', 'products_of_suppliers', 'pos', 'p.id=pos.id_product AND (pv.id IS NULL OR pv.id=pos.id_variation)') ->where(Operator::equals(['pv.ean' => $ean, 'p.ean' => $ean, 'pos.ean' => $ean], 'OR')) ->setMaxResults(1); if (findModule(\Modules::PRODUCTS_BATCHES)) { $eProdOnPosSQL->addSelect(':batchId as id_product_batch') ->setParameter('batchId', $batchId); } $existsProductOnPosition = $eProdOnPosSQL->execute()->fetch(); } $existsProductOnPosition['over_supply'] = $product->over_supply; $piecesToStore = intval($product->checked) - $existsProductOnPosition['pieces']; if ($piecesToStore != 0) { $storeItem = new StoreItem($existsProductOnPosition); $this->storeItemWorker->createStoreItem($storeItem, $piecesToStore, $position, ['inventory' => true], false ); $this->storeIn($existsProductOnPosition, $piecesToStore); $this->logger->logProductMove($storeItem, $piecesToStore, $this->getInventoryPosition(), $position); } $where = [ 'id_position' => $position, 'id_product' => $existsProductOnPosition['id_product'], 'id_variation' => $existsProductOnPosition['id_variation'], ]; if (findModule(\Modules::PRODUCTS_BATCHES)) { $where['id_product_batch'] = $batchId; } sqlQueryBuilder() ->update('warehouse_products') ->set('inventory_date', ':inv_datetime') ->setParameter('inv_datetime', $inventoryDate, 'datetime') ->where(Operator::equalsNullable($where)) ->execute(); } sqlQueryBuilder() ->update('warehouse_positions') ->set('inventory_date', ':inv_datetime') ->setParameter('inv_datetime', $inventoryDate, 'datetime') ->where(Operator::equalsNullable([ 'id' => $position, ])) ->execute(); $result = [ 'result' => true, 'message' => "Inventura pozice {$position_code} provedena", ]; }); return $result; } public function getInventoryPosition() { if ($this->inventoryPosition) { return $this->inventoryPosition; } return $this->inventoryPosition = sqlQueryBuilder() ->select('id') ->from('warehouse_positions') ->where(Operator::like(['code' => 'INVENTURA'])) ->execute()->fetchColumn(); } public function loadProductsCache() { $sqlProducts = sqlQueryBuilder() ->select('p.title as p_title, pv.title as pv_title, COALESCE(pv.ean, p.ean) as ean, COALESCE(pv.code, p.code) as code, p.id as id_product, pv.id as id_variation, \'\' as checked') ->from('products', 'p') ->joinVariationsOnProducts() ->addSelect(\Query\Product::withProductPhotoId(true)) ->groupBy('p.id, pv.id'); $getProductId = function ($prod) { return $prod['id_product'].($prod['id_variation'] ? '_'.$prod['id_variation'] : ''); }; $productsBatches = []; if (findModule(\Modules::PRODUCTS_BATCHES)) { $sqlProducts->addSelect('p.batch_number_require'); $sqlBatches = sqlQueryBuilder()->select('id_product, id_variation, id, code, date_expiry') ->from('products_batches', 'pb') ->execute(); foreach ($sqlBatches as $batch) { $productsBatches[$getProductId($batch)][] = [ 'id' => $batch['id'], 'code' => $batch['code'], 'date_expiry' => $batch['date_expiry'], ]; } } foreach ($sqlProducts->execute() as $prod) { $photo = getImage($prod['id_photo'], null, null, 4, $prod['descr_photo'], strtotime($prod['id_photo_update'])); yield $getProductId($prod) => [ 'batches' => $productsBatches[$getProductId($prod)] ?? [], 'image' => $photo ? ['src' => $photo['src'], 'src_big' => $photo['src_big']] : null, 'ean' => formatEAN($prod['ean']), 'over_supply' => false, ] + array_diff_key($prod, ['id_photo' => 0, 'id_photo_update' => 0, 'descr_photo' => 0]); } } public function loadProductsEans() { $eans = sqlQueryBuilder()->select('COALESCE(pv.ean, p.ean) ean, p.id as id_product, pv.id as id_variation, CONCAT_WS("_", p.id, pv.id) as id') ->fromProducts() ->joinVariationsOnProducts() ->where('COALESCE(pv.ean, p.ean) IS NOT NULL') ->execute(); foreach ($eans as $ean) { yield $ean['ean'] => $ean; } } public function loadProductsSuppliersEans() { $suppliersEans = sqlQueryBuilder()->select('ean, id_product, id_variation, CONCAT_WS("_", id_product, id_variation) as id') ->from('products_of_suppliers') ->where('ean IS NOT NULL') ->execute(); foreach ($suppliersEans as $ean) { yield $ean['ean'] => $ean; } } public function productBatches($ean) { $sqlBatches = sqlQueryBuilder() ->select('pb.id, pb.code, pb.date_expiry') ->fromProducts() ->joinVariationsOnProducts() ->where(Operator::equals(['pv.ean' => $ean, 'p.ean' => $ean], 'OR')) ->innerJoin('pv', 'products_batches', 'pb', 'p.id = pb.id_product AND pv.id <=> pb.id_variation'); $productBatches = []; foreach ($sqlBatches->execute() as $batch) { $productBatches[] = [ 'id' => $batch['id'], 'code' => $batch['code'], 'date_expiry' => $batch['date_expiry'], ]; } return $productBatches; } /** * @param array $existsProductOnPosition * @param int $piecesToStore */ public function storeIn($existsProductOnPosition, $piecesToStore) { $prod = new \Product($existsProductOnPosition['id_product']); $prod->storeIn($existsProductOnPosition['id_variation'], $piecesToStore); } }