Files
kupshop/admin/stockIn.php
2025-08-02 16:30:27 +02:00

797 lines
29 KiB
PHP

<?php
use KupShop\AdminBundle\Util\StockInProductOfSupplierService;
use KupShop\CatalogBundle\Util\Product\ProductPriceWeigher;
use KupShop\KupShopBundle\Context\ContextManager;
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
use KupShop\StoresBundle\Utils\StoresInStore;
use Query\Operator;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
$main_class = 'StockIn';
class StockIn extends Window
{
use DatabaseCommunication;
protected $defaults = [
'paid' => '0',
'vatDisplay' => '0',
'payment_method' => 'prevodem',
'multiplier' => '1',
'id_index' => 'invoice',
];
protected $required = [
'number' => true,
'code' => true,
];
protected $tableName = 'stock_in';
private $index;
protected $index_old;
protected ?StoresInStore $storesInStore = null;
protected ContextManager $contextManager;
protected StockInProductOfSupplierService $stockInProductOfSupplierService;
public function __construct()
{
if (findModule(Modules::STORES)) {
$this->storesInStore = ServiceContainer::getService(StoresInStore::class);
}
$this->contextManager = ServiceContainer::getService(ContextManager::class);
$this->stockInProductOfSupplierService = ServiceContainer::getService(StockInProductOfSupplierService::class);
}
public function recalcTotalPrice()
{
sqlQuery('UPDATE '.getTableName('stock_in').' s
SET total_price=(
SELECT COALESCE(SUM(si.quantity*si.price), 0)+s.transport_price-s.discount
FROM '.getTableName('stock_in_items').' si
WHERE si.id_stock_in=s.id
)
WHERE s.id=:id', ['id' => $this->getID()]);
}
public function get_vars()
{
$vars = parent::get_vars();
$pageVars = getVal('body', $vars);
$acn = $this->getAction();
$pageVars['paid'] = [
'1' => translate('priceType_withVat', 'stockIn'),
'2' => translate('priceType_withoutVat', 'stockIn'),
'0' => translate('priceType_bothVat', 'stockIn'),
'3' => translate('priceType_foreignCurrency', 'stockIn'),
];
$sql = sqlQuery('SELECT id, name FROM '.getTableName('suppliers'));
$pageVars['suppliers'] = ['' => '- Vyber dodavatele -'];
foreach ($sql as $row) {
$pageVars['suppliers'][$row['id']] = $row['name'];
}
if (findModule(Modules::STORES)) {
$pageVars['stores'] = $this->storesInStore->getStoresNames();
}
$pageVars['paymentMethods'] = [
'dobirka' => translate('cod', 'stockIn'),
'prevodem' => translate('bankTransfer', 'stockIn'),
];
$ID = $this->getID();
if ($ID) {
global $cfg;
$id_supplier = $pageVars['data']['id_supplier'];
$date_issued = $pageVars['data']['date_issued'];
$fields = 'si.id, si.id_product, si.name, si.id_variation, si.quantity,
p.title as product_title, pv.title variation_title, si.price, COALESCE(v.vat, si.vat) as vat, p.figure,
COALESCE(pv.price, p.price) as web_price, COALESCE(pv.in_store, p.in_store) as web_in_store,
p.discount as web_discount, COALESCE(pv.ean, p.ean) as ean, pos.code as code_supplier, pos.note as products_of_suppliers_note';
if (!empty($cfg['Modules']['products_variations']['variationCode'])) {
$fields .= ', COALESCE(pv.code, p.code) as code';
} else {
$fields .= ', p.code as code';
}
if (!empty($cfg['Modules']['products']['note'])) {
$fields .= ', COALESCE(pv.note, p.note) as note';
}
if (findModule(Modules::STOCK_IN, Modules::SUB_WEIGHTED_PURCHASE_PRICE)) {
$fields .= ', si.additional_costs';
}
$fields .= ',
(SELECT si2.price FROM stock_in_items si2
LEFT JOIN stock_in st2 ON si2.id_stock_in = st2.id
WHERE st2.id_index = "invoice" AND st2.date_issued <= "'.$date_issued.'" AND st2.id != si.id_stock_in
AND si2.id_product = si.id_product AND ((si.id_variation IS NULL AND si2.id_variation IS NULL) OR si2.id_variation = si.id_variation)
ORDER BY st2.date_issued DESC, st2.id DESC LIMIT 1) AS prev_price';
$orderBy = 'p.id > 0, si.id DESC';
if ($this->getIndex() == 'future') {
$orderBy = 'IF(products_of_suppliers_note IS NULL, 1, 0) ASC, '.$orderBy;
}
$SQL = sqlQuery("SELECT {$fields}
FROM stock_in_items si
LEFT JOIN products p ON p.id=si.id_product
LEFT JOIN products_variations pv ON pv.id=si.id_variation
LEFT JOIN products_of_suppliers pos ON p.id = pos.id_product AND pos.id_supplier = '".$id_supplier."' AND ((pv.id IS NULL AND pos.id_variation IS NULL) OR pos.id_variation = pv.id)
LEFT JOIN vats v ON v.id=p.vat
WHERE si.id_stock_in='".$ID."' GROUP BY si.id ORDER BY ".$orderBy.' ');
$vat = getAdminVat()['value'];
$data = &$pageVars['data'];
$data['transportVat'] = $vat;
$data['transport_price_vat'] = $data['transport_price'] * (1 + ($vat / 100));
$data['total_price_vat'] = $data['transport_price_vat'] - ($data['discount'] * (1 + ($vat / 100)));
$this->unserializeCustomData($data);
if (!empty($data['data']['parent_stock_in'])) {
$data['data']['parent_stock_in'] = sqlQueryBuilder()
->select('*')
->from('stock_in')
->where(Operator::equals(['id' => $data['data']['parent_stock_in']]))
->execute()->fetch();
}
if (findModule(Modules::STORES) && ($data['data']['id_store'] ?? false)) {
$data['isExternalStore'] = ($this->storesInStore->getStores()[$data['data']['id_store']]['type'] ?? false) == StoresInStore::TYPE_EXTERNAL_STORE;
}
$totalQuantity = 0;
$items = [];
foreach ($SQL as $row) {
$row['web_price'] = calcPrice($row['web_price'], 0, $row['web_discount'])->asFloat();
$row['price'] = floatval($row['price']);
if ($row['web_price'] && $row['price']) {
$row['rabat'] = ($row['web_price'] - $row['price']) / $row['price'] * 100;
if ($row['rabat'] < 2) {
$row['color'] = '#9b313b';
$row['bg_color'] = '#FDD7DB';
} elseif ($row['rabat'] < 10) {
$row['color'] = '#9a7a2c';
$row['bg_color'] = '#fceecd';
} else {
$row['color'] = '#699b31';
$row['bg_color'] = '#E5FCCD';
}
if ($row['web_price'] > 0 && $row['web_price'] <= $row['price']) {
$row['bg_color'] = '#FCC479';
}
if ($row['rabat'] > 100) {
$row['bg_color'] = '#DADDFC';
}
}
if ($row['figure'] != 'Y') {
$row['bg_color'] = '#FF858D';
}
$row['web_price_vat'] = $row['web_price'] * (1 + $row['vat'] / 100);
$row['price_vat'] = $row['price'] * (1 + $row['vat'] / 100);
$row['price_all'] = $row['price'] * $row['quantity'];
$row['price_all_vat'] = $row['price'] * $row['quantity'] * (1 + $row['vat'] / 100);
$row['additional_costs'] = floatval($row['additional_costs'] ?? null);
$items[$row['id']] = $row;
$data['total_price_vat'] += ($row['price'] * $row['quantity']) * (1 + $row['vat'] / 100);
$totalQuantity += $row['quantity'];
}
$data['total_price_vat'] = round($data['total_price_vat'], 4); // to fix values like -9.0949470177293E-13
$pageVars['items'] = $items;
$pageVars['totalQuantity'] = $totalQuantity;
$pageVars['itemsCount'] = count($items);
}
// Import from file
if (empty($pageVars['items']) && !empty($data['id_supplier'])) {
$pageVars['import'] = new StockInImport($data);
}
$pageVars['paid2'] = ['1' => 'ANO', '0' => 'NE'];
$pageVars['vatDisplay'] = getVal('vatDisplay');
if (isset($data['data']['currency_symbol']) && !empty($data['data']['currency_symbol'])) {
$pageVars['data']['currency_symbol'] = $data['data']['currency_symbol'];
} else {
$pageVars['data']['currency_symbol'] = '€';
}
if (is_string($pageVars['data']['data'] ?? false)) {
$this->unserializeCustomData($pageVars['data']);
}
$vars['body'] = $pageVars;
return $vars;
}
protected function getFields()
{
$index = $this->getIndex();
if (in_array($index, ['closure', 'future', 'preorder'])) {
$this->required = [];
}
parent::getFields();
}
public function createObject()
{
$data = parent::createObject();
if (empty($data['date_created'])) {
$data['date_created'] = date('d-m-Y H:i:s');
}
if (empty($data['date_issued'])) {
if (in_array($data['id_index'], ['future', 'preorder'])) {
$data['date_issued'] = date('d-m-Y', time() + 86400);
} else {
$data['date_issued'] = date('d-m-Y', time() - 86400);
}
}
if (empty($data['date_expiration'])) {
$data['date_expiration'] = date('d-m-Y', time() + (13 * 86400));
}
return $data;
}
public function getData()
{
$data = parent::getData();
if (!empty($data['date_issued'])) {
$data['date_issued'] = $this->prepareDate($data['date_issued']);
}
if (!empty($data['date_expiration'])) {
$data['date_expiration'] = $this->prepareDate($data['date_expiration']);
}
if (isset($data['multiplier'])) {
$this->preparePrice($data['multiplier']);
}
if (getVal('Submit') == 'recieved') {
if ($this->getIndex() == 'future') {
$this->index_old = 'future';
$this->index = 'invoice';
}
$data['id_index'] = $this->index;
}
if (getVal('Submit')) {
$this->serializeCustomData($data);
}
return $data;
}
public function handleUpdate()
{
$acn = $this->getAction();
$data = $this->getData();
$ID = $this->getID();
$oldMultiplier = null;
$multiplier = $data['multiplier'];
if ($acn == 'edit' && !empty($ID)) {
$closed = returnSQLResult('SELECT closed
FROM '.getTableName('stock_in')." s
WHERE s.id='{$ID}' ");
if ($closed) {
$this->returnError('Nelze upravovat uzavřenou fakturu');
}
// kvůli přepočtu CZK ceny při změně kurzu u naskladnění v cizí měně
$vatDisplay = json_decode($data['data'], true)['vatDisplay'] ?? null;
if ($vatDisplay and $vatDisplay == 3) {
$oldMultiplier = sqlQueryBuilder()
->select('multiplier')
->from('stock_in')
->andWhere(Operator::equals(['id' => $ID]))
->execute()->fetchOne();
}
}
parent::handleUpdate();
if ($this->index_old == 'future' && $this->index == 'invoice') {
// Naskladnění aktualizovat pouze v případě naskladnění, ne aktualizace faktury
sqlQueryBuilder()
->update('stock_in')
->set('date_stock_in', 'NOW()')
->andWhere(Operator::equals(['id' => $ID]))
->execute();
}
$object = $this->getObject();
if (empty($object['number']) && $object['id_index'] == 'invoice') {
$number = returnSQLResult('SELECT MAX(number)+1 FROM '.getTableName('stock_in').' WHERE id_index="invoice"');
if (empty($number)) {
$number = 1;
}
$this->updateSQL('stock_in', ['number' => $number], ['id' => $this->getID()]);
}
$stockin = getVal('stockin', $data, []);
if (findModule(Modules::STOCK_IN, Modules::SUB_WEIGHTED_PURCHASE_PRICE)) {
$this->appendAdditionalCosts($stockin, $object);
}
if (findModule(Modules::STOCK_IN, Modules::SUB_WEIGHTED_PURCHASE_PRICE)) {
$this->productPriceWeigher = ServiceContainer::getService(ProductPriceWeigher::class);
}
if (isset($oldMultiplier) && $oldMultiplier != 0 && ($oldMultiplier != $multiplier)) {
foreach ($stockin as $id => &$item) {
$item['price'] = ($item['price'] / $oldMultiplier) * $multiplier;
}
}
krsort($stockin, SORT_NUMERIC);
sqlGetConnection()->transactional(function () use ($stockin) {
foreach ($stockin as $id => $item) {
$item['id'] = intval($id);
if (!$id) {
continue;
}
$item['quantity'] = str_replace(',', '.', $item['quantity']);
$item = array_merge($this->getItem($item), $item);
if ($this->index_old == 'future' && $this->index == 'invoice') {
// naskladneni
$item['recieved'] = true;
}
$this->recalculateWeightedPrice($item);
if (!empty($item['delete'])) {
$this->handleDeleteValue($item);
continue;
}
if ($id < 0) {
$this->handleAddValue($item);
} else {
$this->handleUpdateValue($item);
}
}
$this->recalcTotalPrice();
});
$vatDisplay = '0';
if (getVal('vatDisplay')) {
$vatDisplay = getVal('vatDisplay');
}
$this->redirect(['vatDisplay' => $vatDisplay, 'ErrStr' => $this->getErrors()[0]]);
return true;
}
public function getItem($item)
{
$row = sqlFetchAssoc(sqlQuery('SELECT si.id_product, si.id_variation, si.quantity as old_quantity
FROM stock_in_items si
WHERE si.id=:id AND si.id_product IS NOT NULL', ['id' => $item['id']]));
return $row ? $row : [];
}
/** Předefinováno na Lashes **/
public function appendAdditionalCosts(&$stockin, $stockInRow)
{
$additionalsCosts = toDecimal($stockInRow['transport_price']);
$totalPrice = \DecimalConstants::zero();
foreach ($stockin as $id => &$item) {
$item['price'] = $this->preparePrice($item['price']);
// fix Division by zero - convert string to float (quantity muze byt napr. "0.0000")
$item['quantity'] = $this->preparePrice($item['quantity']);
$item['additional_costs'] = 0;
if (!$item['price'] || !$item['quantity']) {
continue;
}
$totalPrice = $totalPrice->add(toDecimal($item['price'])->mul(toDecimal($item['quantity']))->abs());
}
foreach ($stockin as $id => &$item) {
if (!$item['price'] || !$item['quantity']) {
continue;
}
$itemsPrice = toDecimal($item['price'])->mul(toDecimal($item['quantity']))->abs();
$itemsPiecesPerc = $itemsPrice->div($totalPrice);
$item['additional_costs'] = $additionalsCosts->mul($itemsPiecesPerc)->div(toDecimal($item['quantity']))->asFloat();
}
return $stockin;
}
public function handleDelete()
{
if (!findRight('INSTORE_STOCKIN_ERASE')) {
redirect('launch.php?s=error.php&id=1');
}
$ID = $this->getID();
$SQL = sqlQuery('SELECT si.id_product, si.id_variation, si.quantity
FROM '.getTableName('stock_in_items')." si
WHERE si.id_stock_in={$ID} AND si.id_product IS NOT NULL");
while (($row = sqlFetchAssoc($SQL)) !== false) {
$this->storeIn($row['id_product'], $row['id_variation'], -$row['quantity']);
}
writeDownActivity(sprintf(translate('activityDeleted'), $ID));
// smazat
sqlQuery('DELETE FROM '.getTableName('stock_in')." WHERE id='{$ID}' ");
redirect("launch.php?s={$this->getName()}.php&acn=erased");
}
public function handleDeleteValue($item)
{
if (!empty($item['id_product'])) {
$this->storeIn($item['id_product'], $item['id_variation'], -$item['old_quantity']);
}
sqlQuery('DELETE FROM stock_in_items WHERE id=:id', ['id' => $item['id']]);
}
public function handleAddValue($item)
{
$data = $this->getData();
$ID = $this->getID();
$item['id_stock_in'] = $ID;
$this->preparePrice($item['price']);
$this->preparePrice($item['price_vat']);
if (empty($item['price'])) {
$item['price'] = 0;
}
if (empty($item['price_vat'])) {
$item['price_vat'] = 0;
}
if (empty($item['quantity'])) {
$item['quantity'] = 0;
}
$fields = ['id_stock_in', 'quantity', 'price', 'name', 'vat'];
if (findModule(Modules::STOCK_IN, Modules::SUB_WEIGHTED_PURCHASE_PRICE)) {
$fields[] = 'additional_costs';
}
if (!empty($item['id_product'])) {
if (empty(intval($item['id_product']))) {
return false;
}
$fields[] = 'id_product';
$fields[] = 'id_variation';
if (!empty($item['id_product_text'])) {
$item['name'] = $item['id_product_text'];
}
if (empty($item['id_variation'])) {
$item['id_variation'] = null;
} else {
$item['name'] = Variations::fillInProductTitle($item['id_variation'], $item['name']);
}
$vat = returnSQLResult('SELECT v.vat
FROM '.getTableName('products').' p
JOIN '.getTableName('vats')." v ON v.id=p.vat
WHERE p.id={$item['id_product']} ");
$item['vat'] = (float) $vat;
if (empty($item['price'])) {
$item['price'] = $item['price_vat'] / (1 + ($vat / 100));
}
} else {
if (empty($item['product_text'])) {
return false;
}
$vat = getAdminVat()['value'];
if (empty($item['quantity'])) {
$item['quantity'] = 1;
}
if (empty($price)) {
$item['price'] = $item['price_vat'] / (1 + ($vat / 100));
}
$item['name'] = $item['product_text'];
$fields[] = 'name';
$item['vat'] = $vat;
}
$SQLfields = $this->getSQLFields($item, $fields);
$this->insertSQL('stock_in_items', $SQLfields);
if (!empty($item['id_product'])) {
// Update store
$this->storeIn($item['id_product'], $item['id_variation'], $item['quantity']);
// Update suppliers code
$item['supplier_code'] = trim($item['supplier_code']) ?: null;
$GLOBALS['code'] = $item['supplier_code'];
try {
$this->stockInProductOfSupplierService->updateOrInsertProductSupplier($item, $data);
} catch (Exception|\Doctrine\DBAL\Driver\Exception) {
$this->addError("Nepodařilo se uložit kód dodavatele: {$item['supplier_code']}, položky: {$item['name']}");
}
}
}
public function handleUpdateValue($item)
{
if (empty($item['price']) && $item['id_product']) {
$vat = returnSQLResult('SELECT v.vat
FROM products p
JOIN vats v ON v.id=p.vat
WHERE p.id=:id_product', $item);
$item['price'] = $item['price_vat'] / (1 + ($vat / 100));
} else {
$this->preparePrice($item['price']);
}
if ($item['id_product']) {
if ($this->index_old == 'future' && $this->index == 'invoice') {
$quantity = $item['quantity'];
if (findModule(Modules::PRODUCTS, Modules::SUB_PRICE_BUY)
&& findModule(Modules::PRODUCTS, Modules::SUB_PRICE_BUY) !== 'do_not_update'
&& !findModule(Modules::STOCK_IN, Modules::SUB_WEIGHTED_PURCHASE_PRICE)
) {
$qb = sqlQueryBuilder()
->update(($item['id_variation'] ?? false) ? 'products_variations' : 'products')
->set('price_buy', $item['price']);
if ($item['id_variation'] ?? false) {
$qb->andWhere(Operator::equals(['id' => $item['id_variation']]));
} else {
$qb->andWhere(Operator::equals(['id' => $item['id_product']]));
}
$qb->execute();
}
// Naskladnění aktualizovat pouze v případě naskladnění, ne aktualizace faktury
sqlQueryBuilder()
->update('products')
->set('date_stock_in', 'NOW()')
->andWhere(Operator::equals(['id' => $item['id_product']]))
->execute();
} else {
$quantity = $item['quantity'] - $item['old_quantity'];
}
$this->storeIn($item['id_product'], $item['id_variation'], $quantity);
}
$SQLFields = [
'quantity' => $item['quantity'],
'price' => $item['price'],
];
if (findModule(Modules::STOCK_IN, Modules::SUB_WEIGHTED_PURCHASE_PRICE)) {
$SQLFields['additional_costs'] = $item['additional_costs'];
}
$this->updateSQL('stock_in_items', $SQLFields, ['id' => $item['id']]);
$this->recalcTotalPrice();
}
public function recalculateWeightedPrice($item)
{
$index = $this->getIndex();
if (in_array($index, ['closure', 'future', 'preorder']) || empty($item['price'])) {
return false;
}
if (findModule(Modules::STOCK_IN, Modules::SUB_WEIGHTED_PURCHASE_PRICE)) {
$this->productPriceWeigher->updateWeightedPurchasePrice($item);
}
}
public function handleClose()
{
$ID = $this->getID();
sqlQuery('UPDATE '.getTableName('stock_in')." s
SET s.closed=1
WHERE s.id={$ID}");
$ErrStr = "Záznam číslo {$ID} uzavřen.";
// presmerovani
redirect('launch.php?s=stockIn.php&acn=edit&refresh=parent&ID='.$ID.'&ErrStr='.$ErrStr);
}
public function handleImport()
{
$data = $this->getData();
$data['id'] = $this->getID();
$import = new StockInImport($data, $this->getIndex());
try {
$import->load_supplier_settings();
} catch (Exception $e) {
$this->returnError('Chyba importu: '.$e->getMessage());
}
if (!$import->import($_FILES['import'])) {
$this->returnError('Chyba importu: '.join(', ', $import->errors));
}
$this->recalcTotalPrice();
$this->returnOK('Import proběhl: '.join(', ', $import->errors));
}
public function handleCreateProduct()
{
$stockInID = $this->getID();
$itemID = getVal('itemID');
$success = false;
if ($stockInID && $itemID) {
try {
sqlGetConnection()->transactional(function () use ($itemID, $stockInID, &$success) {
if ($item = $this->selectSQL('stock_in_items', ['id' => $itemID])->fetch()) {
$stockIn = $this->selectSQL('stock_in', ['id' => $stockInID])->fetch();
$name = $item['name'];
preg_match('/\(kód: (.*?)\)/', $name, $match);
if (!empty($match)) {
$name = str_replace($match[0], '', $name);
$code = $match[1];
$vatID = getAdminVat()['id'];
$vat = getAdminVat()['value'];
$insert = [
'title' => $name,
// 'code' => $code,
'vat' => $vatID,
'figure' => 'N',
'date_added' => date('Y-m-d H:i:s'),
];
if ($this->getIndex() == 'invoice') {
$insert['in_store'] = $item['quantity'] ? $item['quantity'] : 0;
}
if (findModule(Modules::PRODUCTS, Modules::SUB_PRICE_BUY)) {
$insert['price_buy'] = toDecimal($item['price'])->addVat($vat);
}
$this->insertSQL('products', $insert);
$productID = sqlInsertId();
$this->updateSQL(
'stock_in_items',
[
'id_product' => $productID,
'vat' => $vat,
],
['id' => $itemID]
);
$this->insertSQL(
'products_of_suppliers',
[
'id_product' => $productID,
'id_supplier' => $stockIn['id_supplier'],
'code' => $code,
]
);
$success = true;
}
}
});
if ($success) {
$this->returnOK('Produkt byl úspěšně vytvořen');
} else {
$this->returnError('Produkt se nepodařilo vytvořit');
}
} catch (Exception $e) {
if (strpos($e->getMessage(), '1062 Duplicate entry')) {
$this->returnError('Nepodařilo se vytvořit produkt, protože produkt s takovým kódem už existuje.');
} else {
$this->returnError('Při vytváření produktu se vyskytla chyba: '.$e->getMessage());
}
}
}
}
public function getIndex()
{
if (is_null($this->index)) {
try {
$this->index = $this->getObject()['id_index'];
} catch (NotFoundHttpException) {
$this->index = '';
}
}
return $this->index;
}
public function storeIn($id_product, $id_variation, $quantity)
{
$index = $this->getIndex();
if (in_array($index, ['closure', 'future', 'preorder'])) {
return false;
}
sqlGetConnection()->transactional(function () use ($quantity, $id_variation, $id_product) {
$stockIn = true;
if (findModule(Modules::STORES)) {
$data = $this->getCustomData();
$store_id = ($data['id_store'] ?? 1);
$SQLfields = [
'id_store' => $store_id,
'id_product' => $id_product,
'id_variation' => $id_variation,
'quantity' => $quantity,
];
ServiceContainer::getService(\KupShop\KupShopBundle\Util\LoggingContext::class)->activateStockIn($this->getID(), function () use ($SQLfields) {
$this->storesInStore->updateStoreItem($SQLfields);
});
$stores = $this->storesInStore->getStores();
$store = $stores[$store_id];
if ($store['type'] == StoresInStore::TYPE_EXTERNAL_STORE) {
$stockIn = false;
}
}
if ($stockIn) {
$prod = new Product($id_product);
$prod->storeIn($id_variation, $quantity);
}
});
return true;
}
public function hasRights($name = null)
{
switch ($name) {
case Window::RIGHT_DUPLICATE:
return false;
case Window::RIGHT_DELETE:
return findRight('INSTORE_STOCKIN_ERASE');
default:
return parent::hasRights($name);
}
}
}