245 lines
9.2 KiB
PHP
245 lines
9.2 KiB
PHP
<?php
|
|
|
|
namespace KupShop\WarehouseBundle\Util;
|
|
|
|
use KupShop\WarehouseBundle\Entity\StoreItem;
|
|
use Query\Operator;
|
|
|
|
class InventoryWorker
|
|
{
|
|
/**
|
|
* @var Logger
|
|
*/
|
|
private $logger;
|
|
/**
|
|
* @var StoreItemWorker
|
|
*/
|
|
private $storeItemWorker;
|
|
|
|
public function __construct(Logger $logger, StoreItemWorker $storeItemWorker)
|
|
{
|
|
$this->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);
|
|
}
|
|
}
|