first commit

This commit is contained in:
2025-08-02 16:30:27 +02:00
commit 23646bfcee
14851 changed files with 1750626 additions and 0 deletions

View File

@@ -0,0 +1,23 @@
<?php
use KupShop\AdminBundle\AdminList\BaseList;
class AdminsList extends BaseList
{
protected $tableDef = [
'id' => 'id',
'fields' => [
'Login' => ['field' => 'login'],
'Aktivní' => ['field' => 'active', 'render' => 'renderBoolean'],
'Všechna práva' => ['field' => 'superuser', 'render' => 'renderBoolean'],
'Expirace' => ['field' => 'date_valid', 'render' => 'renderDateTime'],
],
];
public function getQuery()
{
$qb = sqlQueryBuilder()->select('id', 'login', 'active', 'IF(privilege = "ALL_RIGHTS", "Y", "N") as superuser', 'date_valid')->from('admins');
return $qb;
}
}

View File

@@ -0,0 +1,52 @@
<?php
namespace Admin\Lists;
use KupShop\AdminBundle\AdminList\BaseList;
use KupShop\CatalogBundle\Query\Search;
use Query\QueryBuilder;
class ArtauthorsList extends BaseList
{
protected $tableName = 'articles_authors';
protected ?string $tableAlias = 'aa';
protected $tableDef = [
'id' => 'id',
'fields' => [
'ID' => ['field' => 'id', 'size' => 0.5],
'Jméno' => ['field' => 'name', 'render' => 'renderName', 'fieldType' => BaseList::TYPE_STRING],
'Přezdívka' => ['field' => 'nick', 'fieldType' => BaseList::TYPE_STRING],
'Poznámka' => ['field' => 'note', 'fieldType' => BaseList::TYPE_STRING],
'Registrován' => ['field' => 'date_reg', 'render' => 'renderDate', 'fieldType' => BaseList::TYPE_DATE],
],
];
public function renderName($values, $column)
{
$name = $this->getListRowValue($values, $column['field']);
return $name.' '.$values['surname'];
}
public function getFilterQuery(): QueryBuilder
{
$qb = parent::getFilterQuery();
if ($name = getVal('name')) {
$qb->andWhere(Search::searchFields(
search_term: $name,
fields: [
['field' => 'name', 'match' => 'both'],
['field' => 'surname', 'match' => 'both'],
['field' => 'nick', 'match' => 'both'],
],
operator: 'OR'
));
}
return $qb;
}
}
return ArtauthorsList::class;

View File

@@ -0,0 +1,189 @@
<?php
namespace Admin\Lists;
use KupShop\AdminBundle\AdminList\BaseList;
use KupShop\AdminBundle\AdminList\FiltersStorage;
use KupShop\AdminBundle\Query\Invert;
use KupShop\I18nBundle\Admin\Util\ListTranslationsFigureBadges;
use KupShop\I18nBundle\Translations\ArticlesTranslation;
use KupShop\KupShopBundle\Util\HtmlBuilder\HTML;
use KupShop\KupShopBundle\Util\StringUtil;
use Query\Operator;
class ArticlesList extends BaseList
{
use FiltersStorage;
use ListTranslationsFigureBadges;
protected $showMassEdit = true;
protected $tableName = 'articles';
protected ?string $tableAlias = 'a';
protected $orderParam = [
'sort' => 'dateAdded',
'direction' => 'DESC',
];
protected $tableDef = [
'id' => 'a.id',
'fields' => [
'title' => ['translate' => true, 'field' => 'a.title', 'size' => 2.5, 'fieldType' => BaseList::TYPE_STRING],
/* 'Číslo' => ['field' => 'a.id', 'size' => 0.5], */
'section' => ['translate' => true, 'field' => 'ab.name', 'size' => 0.5],
'showArticle' => ['translate' => true, 'field' => 'a.figure', 'render' => 'renderBoolean', 'size' => 0.5, 'spec' => 'a.figure', 'fieldType' => BaseList::TYPE_BOOL],
'type' => ['translate' => true, 'field' => 'a.type', 'render' => 'renderArticleType', 'size' => 0.5, 'spec' => 'a.type', 'fieldType' => ArticlesList::TYPE_LIST],
'seen' => ['translate' => true, 'field' => 'a.seen', 'render' => 'renderSeen', 'size' => 0.5],
'dateAdded' => ['translate' => true, 'field' => 'datef', 'render' => 'renderDateTime', 'raw_field' => 'a.date', 'size' => 1.5],
'date_created' => ['translate' => true, 'field' => 'a.date_created', 'render' => 'renderDateTime', 'raw_field' => 'a.date_created', 'size' => 1.5, 'visible' => 'N'],
'contentEditing' => ['translate' => true, 'render' => 'renderBlocekBtn', 'class' => 'hidden-label alignRight'],
'leadIn' => ['translate' => true, 'field' => 'a.lead_in', 'visible' => 'N', 'spec' => 'a.lead_in', 'fieldType' => BaseList::TYPE_STRING],
'link' => ['translate' => true, 'field' => 'a.link', 'visible' => 'N', 'spec' => 'a.link', 'fieldType' => BaseList::TYPE_STRING],
'comments' => ['translate' => true, 'field' => 'a.comments', 'visible' => 'N', 'spec' => 'a.comments', 'fieldType' => BaseList::TYPE_BOOL],
'url' => ['translate' => true, 'field' => 'a.url', 'visible' => 'N', 'spec' => 'a.url', 'fieldType' => BaseList::TYPE_STRING],
'metaTitle' => ['translate' => true, 'field' => 'a.meta_title', 'visible' => 'N', 'spec' => 'a.meta_title', 'fieldType' => BaseList::TYPE_STRING],
'metaDescription' => ['translate' => true, 'field' => 'a.meta_description', 'visible' => 'N', 'spec' => 'a.meta_description', 'fieldType' => BaseList::TYPE_STRING],
],
];
public function customizeMassTableDef($tableDef)
{
$tableDef = parent::customizeMassTableDef($tableDef);
$tableDef['fields']['type']['fieldOptions'] = [
'A' => translate('article', 'articles'),
'L' => translate('link', 'articles'),
];
return $tableDef;
}
public function customizeTableDef($tableDef): array
{
$tableDef = parent::customizeTableDef($tableDef);
if (findModule(\Modules::TRANSLATIONS)) {
$tableDef['fields']['translationsFigure'] = $this->getTranslationsFigureField(
ArticlesTranslation::class,
column: ['translation_section' => 'translations'],
);
}
return $tableDef;
}
public function renderArticleType($values, $column)
{
$value = $this->getListRowValue($values, $column['field']);
if ($value == 'A') {
return 'článek';
} else {
return 'odkaz';
}
}
public function renderSeen($values, $column)
{
$value = $this->getListRowValue($values, $column['field']);
return "{$value}x";
}
public function renderBlocekBtn($values, $clumn)
{
$url = path('kupshop_content_articles_article_1', [
'IDa' => $values['id'],
'slug' => StringUtil::slugify($values['title']),
]);
return HTML::create('a')->class('btn btn-primary btn-xs')
->attr('href', $url.'?inlineEditable=1')
->attr('target', '_blank')
->tag('span')->class('bi bi-pencil-square')->end()->end();
}
public function getQuery()
{
/* TODO pokud je článek ve 2 sekcích, vypíše se jen první */
$qb = sqlQueryBuilder();
$qb->select('a.id, a.title, a.seen, ab.name, a.date as datef, a.date_created')
->from('articles', 'a')
->leftJoin('a', 'articles_relation', 'ar', 'ar.id_art = a.id')
->leftJoin('ar', 'articles_branches', 'ab', 'ab.id = ar.id_branch')
->groupBy('a.id');
extract($_GET, EXTR_SKIP | EXTR_REFS);
// ###########
if (!empty($figure) && ($figure == 'Y' || $figure == 'N')) {
$qb->andWhere(Operator::equals(['a.figure' => $figure]));
}
// ###########
if (!empty($_GET['IDsec'])) {
$qb->andWhere('a.id = ar.id_art')
->andWhere(Operator::equals(['ar.id_branch' => $_GET['IDsec']]));
}
// ###########
if (!empty($_GET['IDa'])) {
$qb->andWhere(Operator::equals(['a.id' => $_GET['IDa']]));
}
if (!empty($_GET['title'])) {
$qb->andWhere(Operator::like(['a.title' => '%'.$_GET['title'].'%']));
}
if (!empty($_GET['figure'])) {
$qb->andWhere(
Invert::checkInvert(
Operator::inStringArray((array) $_GET['figure'], 'a.figure'),
isset($_GET['figure_invert'])
)
);
}
// ###########
if (!empty($_GET['IDauth'])) {
$qb->from('articles_authors_relation', 'aar')
->andWhere('aar.id_art = a.id')
->andWhere(Operator::equals(['aar.id_auth' => $_GET['IDauth']]));
}
// ###########
if (!empty($dateFrom) || !empty($dateTo)) {
if (!empty($dateFrom) && !isset($dateFromNotDecide)) {
$qb->andWhere('a.date >= :dateFrom')
->setParameter('dateFrom', $this->prepareDate($dateFrom).' 00:00:00');
}
if (!empty($dateTo) && !isset($dateToNotDecide)) {
$qb->andWhere('a.date <= :dateTo')
->setParameter('dateTo', $this->prepareDate($dateTo).' 23:59:59');
}
}
// ###########
if (!empty(getVal('tags'))) {
$qb->leftJoin('a', 'articles_tags_relation', 'atr', 'atr.id_article = a.id')
->leftJoin('atr', 'articles_tags', 'at', 'at.id = atr.id_tag')
->andWhere(Operator::inIntArray(getVal('tags'), 'at.id'));
}
// zobrazeni zbozi s novymu komentari
if (isset($comments) && $comments == 'new' && isset($adminID) && $adminID > 0) {
$dateLogin = returnSQLResult('SELECT date_access
FROM '.getTableName('admins_accesses').'
WHERE id_admin='.intval($adminID)." AND login_status='OK'
ORDER BY id DESC
LIMIT 1, 1");
if (empty($dateLogin)) {
$dateLogin = date('Y-m-d').' 00:00:00';
}
$qb->from('articles as a, comments as c')
->andWhere('c.type="article" AND c.id_item = a.id AND c.date >= :dateLogin')
->setParameter('dateLogin', $dateLogin);
}
// ###########
return $qb;
}
}
return ArticlesList::class;

View File

@@ -0,0 +1,27 @@
<?php
use KupShop\AdminBundle\AdminList\BaseList;
class ArticlesTagsList extends BaseList
{
protected $showMassEdit = true;
protected $tableName = 'articles_tags';
protected ?string $tableAlias = 'at';
protected $tableDef = [
'id' => 'id',
'fields' => [
'ID' => ['field' => 'at.id', 'size' => 1],
'tag' => ['translate' => true, 'field' => 'at.tag', 'size' => 5, 'spec' => 'at.tag', 'fieldType' => BaseList::TYPE_STRING],
],
];
public function getQuery()
{
$qb = sqlQueryBuilder()
->select('id')
->from('articles_tags', 'at');
return $qb;
}
}

View File

@@ -0,0 +1,137 @@
<?php
use KupShop\AdminBundle\AdminList\BaseList;
use KupShop\KupShopBundle\Util\HtmlBuilder\HTML;
class ArtsectionsList extends BaseList
{
protected $template = 'list/artsections.tpl';
protected $tableDef = [
'id' => 'id',
'fields' => [
'Sekce' => ['field' => 'title', 'render' => 'getTitle', 'size' => 4],
'Popis' => ['field' => 'descr', 'render' => 'renderHTML', 'class' => 'getDescriptionClass', 'size' => 6],
'Zobrazuje se' => ['field' => 'figure', 'render' => 'renderFigure', 'class' => 'alignRight hidden-label', 'size' => 2],
],
'class' => null,
];
public function getTitle($values, $column)
{
return [
HTML::create('span')
->class('drag-drop-mover')
->tag('i')
->class('bi bi-arrows-move handle')
->end(),
HTML::create('span')
->class('bi bi-dash-circle opener '.(count($values['submenu']) > 0 ? '' : 'disabled')),
HTML::create('strong')
->attr('class', 'text-dark')
->text($this->getListRowValue($values, $column['field'])),
];
}
public function renderFigure($values, $column)
{
return $values['figure'] === 'N' ? $this->renderBadge(translate('figureN', 'menulinks'), 'badge-pastel-default', 'eye-slash-fill m-r-1') : '';
}
public function getDescriptionClass($values)
{
return 'columnDescription';
}
public function getQuery()
{
return sqlQueryBuilder();
}
public function handleDrag()
{
$tree = getVal('tree');
if ($tree) {
$id_topsection = getVal('target', $tree);
if (!$id_topsection) {
$id_topsection = null;
}
// update
sqlQueryBuilder()
->update('articles_branches')
->set('position', 'position+1')
->where(\Query\Operator::equalsNullable(['top_branch' => $id_topsection]))
->andWhere('position >= :position')
->setParameter('position', $tree['position'])
->execute();
sqlQueryBuilder()
->update('articles_branches')
->directValues([
'top_branch' => $id_topsection,
'position' => $tree['position'],
])
->where(\Query\Operator::equalsNullable(['id' => $tree['id']]))
->execute();
self::orderTreeLevel($id_topsection);
clearCache('article-sections-', true);
exit('OK');
}
exit('Err');
}
public static function orderTreeLevel($id_topsection)
{
$SQL = sqlQueryBuilder()
->select('id, position')
->from('articles_branches')
->where(\Query\Operator::equalsNullable(['top_branch' => $id_topsection]))
->orderBy('position, name', 'ASC')
->execute();
foreach ($SQL as $index => $row) {
if ($row['position'] === null || $row['position'] != $index) {
sqlQuery("UPDATE articles_branches SET position={$index} WHERE id={$row['id']}");
}
}
}
public function getSQL(Query\QueryBuilder $qb)
{
return ['SQL' => $this->articlesSections(null)];
}
public function articlesSections($topCat)
{
$data = [];
/*$SQL = sqlQuery('SELECT ab.id, ab.name, ab.descr, ab.figure
FROM '.getTableName('articles_branches')." AS ab
WHERE ab.top_branch='".$topCat."'
ORDER BY ab.name ASC");*/
$SQL = sqlQueryBuilder()
->select('ab.id', 'ab.name', 'ab.descr', 'ab.figure')
->from('articles_branches', 'ab')
->where(\Query\Operator::equalsNullable(['ab.top_branch' => $topCat]))
->orderBy('ab.position, ab.name', 'ASC')->execute();
foreach ($SQL as $key => $row) {
$data[$key]['id'] = $row['id'];
$data[$key]['descr'] = $row['descr'];
$data[$key]['figure'] = $row['figure'];
$data[$key]['level'] = $topCat;
$data[$key]['title'] = $row['name'];
$data[$key]['submenu'] = $this->articlesSections($row['id']);
}
return $data;
}
}

View File

@@ -0,0 +1,42 @@
<?php
use KupShop\AdminBundle\AdminList\BaseList;
class Automatic_importList extends BaseList
{
protected $tableDef = [
'id' => 'id',
'fields' => [
'ID' => ['field' => 'i.id'],
'Jméno' => ['field' => 'i.name', 'size' => 1.5],
'Dodavatel' => ['field' => 'sup_name', 'size' => 1.5],
'Poslední synchronizace' => ['field' => 'last_sync'],
'Synchronizováno položek' => ['field' => 'i.last_count'],
'Interval (dnů)' => ['field' => 'i.interval'],
],
];
public function getQuery()
{
$qb = sqlQueryBuilder()
->select('i.id', 'i.id ID', 'i.name', 's.name AS sup_name', 'DATE_FORMAT(i.last_sync, \''.$GLOBALS['dbcfg']['date_format'].' '.$GLOBALS['dbcfg']['time_format'].'\') as last_sync', 'i.last_count', 'i.interval')
->from('import', 'i')
->leftJoin('i', 'suppliers', 's', 'i.id_supplier=s.id');
extract($_GET, EXTR_SKIP | EXTR_REFS);
if (!empty($IDi)) {
$qb->where(\Query\Operator::inIntArray($IDs, 's.id'));
}
// ###########
if (isset($supplier) && $supplier != '') {
$qb->where('s.name LIKE :supplier_name')
->orWhere('s.ico LIKE :supplier_name')
->setParameter('supplier_name', '%'.$supplier.'%');
unset($fields, $name);
}
return $qb;
}
}

View File

@@ -0,0 +1,152 @@
<?php
use KupShop\AdminBundle\AdminList\BaseList;
use KupShop\KupShopBundle\Util\HtmlBuilder\HTML;
class DbbackupList extends BaseList
{
protected $template = 'list/dbbackup.tpl';
protected $tableDef = [
'id' => '',
'fields' => [
'Záloha' => ['field' => 'name'],
'Velikost' => ['field' => 'size', 'render' => 'renderSize'],
'Datum vytvoření' => ['field' => 'date', 'render' => 'renderTimestamp'],
'Smazat zálohu' => ['field' => 'name', 'render' => 'renderDelete'],
'Pojmenovat zálohu' => ['field' => 'name', 'render' => 'renderRename'],
'Obnovit zálohu databáze' => ['field' => 'name', 'render' => 'renderRestore'],
'Stáhnout' => ['field' => 'download', 'render' => 'renderDownload'],
],
'class' => 'dbbackup',
];
protected $showExport = false;
public function renderDownload($values, $column)
{
return HTML::create('a')
->attr('href', 'launch.php?s=dbbackup.php&acn=download&file='.$values['name'])
->text('Stáhnout');
}
public function renderSize($values, $column)
{
return $this->getListRowValue($values, $column['field']).' kB';
}
public function renderTimestamp($values, $column)
{
return date('d.m.Y H:i:s', $this->getListRowValue($values, $column['field']));
}
public function renderDelete($values, $column)
{
if (findRight('OTH_BACKUP_ERASE')) {
$value = $this->getListRowValue($values, $column['field']);
return HTML::create('a')
->class('confirm')
->attr('title', 'Smazat zálohu')
->attr('href', 'launch.php?s=dbbackup.php&acn=do&do=erase&dbBackup='.urlencode($value))
->tag('span')
->class('btn btn-xs btn-secondary')
->tag('i')
->class('bi bi-trash')
->end()
->end();
}
return '';
}
public function renderRename($values, $column)
{
if (findRight('OTH_BACKUP_ERASE')) {
$value = $this->getListRowValue($values, $column['field']);
$name = preg_replace('/.sql(.bz2)?/i', '', $value);
return HTML::create('a')
->attr('data-rename', $name)
->attr('title', 'Pojmenovat zálohu')
->attr('href', 'launch.php?s=dbbackup.php&acn=do&do=rename&dbBackup='.urlencode($value))
->tag('span')
->class('btn btn-xs btn-secondary')
->tag('i')
->class('bi bi-tag')
->end()
->end();
}
return '';
}
public function renderRestore($values, $column)
{
if (findRight('OTH_BACKUP_REFRESH') && !isLive()) {
$value = $this->getListRowValue($values, $column['field']);
return HTML::create('a')
->class('confirm')
->attr('title', 'Obnovit zálohu databáze?
Pozor! Budou obnovena všechna data.
Veškeré změny provedené v e-shopu po datu zálohy budou ztraceny. Včetně objednávek, stránek a dalších.
Chcete pokračovat')
->attr('href', 'launch.php?s=dbbackup.php&acn=do&do=restore&dbBackup='.urlencode($value))
->tag('span')
->class('btn btn-xs btn-secondary')
->tag('i')
->class('bi bi-check-circle')
->end()
->end();
}
return '';
}
public function getSQL(Query\QueryBuilder $qb)
{
$SQL = [];
if ($Dir = @opendir($GLOBALS['cfg']['Path']['db_backup'])) {
$files = [];
while ($fileThis = @readdir($Dir)) {
if (!@is_dir($fileThis) && preg_match('/\\.(sql|gz|bz2)$/i', $fileThis)) {
$files[] = $fileThis;
}
}
foreach ($files as $file) {
$path = $GLOBALS['cfg']['Path']['db_backup'].$file;
$SQL[] = [
'name' => $file,
'date' => filemtime($path),
'size' => ceil(filesize($path) / 1000),
];
}
// Sort by creation date
usort($SQL, function ($a, $b) {
return $a['date'] > $b['date'] ? -1 : 1;
});
}
return ['SQL' => $SQL];
}
public function getQuery()
{
return sqlQueryBuilder();
}
public function handleExportDataFiles()
{
$exportDataFiles = \KupShop\KupShopBundle\Util\Compat\ServiceContainer::getService(\KupShop\AdminBundle\Util\Export\ExportDataFiles::class);
$exportDataFiles->export();
}
}

View File

@@ -0,0 +1,151 @@
<?php
use KupShop\AdminBundle\AdminList\BaseList;
use KupShop\AdminBundle\Query\Invert;
use KupShop\KupShopBundle\Query\JsonOperator;
use Query\Operator;
class DeliveryDeliveryList extends BaseList
{
use AdminListSortable;
protected $template = 'listSortable.tpl';
protected $showMassEdit = true;
protected $tableName = 'delivery_type_delivery';
protected ?string $tableAlias = 'dtd';
protected $tableDef = [
'id' => 'id',
'fields' => [
'Pořadí' => ['field' => 'position', 'render' => 'renderPosition', 'size' => 0.3, 'fieldType' => BaseList::TYPE_POSITION],
'Název' => ['field' => 'name_admin', 'fieldType' => BaseList::TYPE_STRING],
'Název v košíku' => ['field' => 'name', 'visible' => 'N', 'fieldType' => BaseList::TYPE_STRING],
'Termín doručení' => ['field' => 'time_days', 'render' => 'renderDelivery', 'class' => 'center'],
'Cena s DPH' => ['field' => 'price', 'render' => 'renderPriceVat', 'class' => 'right', 'fieldType' => BaseList::TYPE_PRICE_WITH_CURRENCY],
'Cena s DPH (reg.)' => ['field' => 'price_registered', 'visible' => 'N', 'render' => 'renderPriceVat', 'class' => 'right', 'fieldType' => BaseList::TYPE_PRICE_WITH_CURRENCY],
'Nezapočítat od' => ['field' => 'price_dont_countin_from', 'render' => 'renderPrice', 'class' => 'right', 'fieldType' => BaseList::TYPE_FLOAT_WITH_CURRENCY],
'Nezapočítat od (reg.)' => ['field' => 'price_dont_countin_from_reg', 'visible' => 'N', 'render' => 'renderPrice', 'class' => 'right', 'fieldType' => BaseList::TYPE_FLOAT_WITH_CURRENCY],
],
];
public function __construct()
{
if (findModule('deliveries')) {
$this->tableDef['fields']['Osobní odběr'] = ['field' => 'in_person', 'raw_field' => '(class = "OsobniOdber")', 'render' => 'renderInPerson', 'class' => 'center'];
$this->tableDef['fields']['Dopravce'] = ['field' => 'class', 'render' => 'renderDeliveryClass'];
}
if (findModule('delivery_pricelist')) {
$this->tableDef['fields']['Ceník dopravy'] = ['field' => 'id_pricelist', 'render' => 'renderPricelist'];
}
}
public function renderPriceList($values, $column)
{
$pricelistId = $values[$column['field']];
if ($pricelistId == null) {
return 'nepoužívat';
} else {
return $this->getPricelistName($pricelistId);
}
}
public function renderInPerson($values, $column)
{
if (isset($values['in_person'])) {
return $this->renderBoolean($values, $column);
}
$delivery = Delivery::getClass($values['class']);
$values['in_person'] = is_null($delivery) ? false : $delivery->isInPerson();
return $this->renderBoolean($values, $column);
}
public function renderDelivery($values, $column)
{
$value = $this->getListRowValue($values, $column['field']);
$hours = $this->getListRowValue($values, 'time_hours');
if ($value === '0') {
$value = 'ihned';
} elseif ($value > 0) {
$value .= ' dnů';
}
if ($hours) {
$value .= " do {$hours}";
}
return $value;
}
public function renderDeliveryClass($values, $column)
{
$value = $this->getListRowValue($values, $column['field']);
if (!$value) {
return $value;
}
$class = Delivery::getClass($value);
return $class::$className;
}
private function getPricelistName($id)
{
/** @var \Doctrine\ORM\EntityManager $em */
$em = \KupShop\KupShopBundle\Util\Compat\ServiceContainer::getService('doctrine.orm.entity_manager');
$repository = $em->getRepository(\KupShop\DeliveryPriceListBundle\Entity\PriceList::class);
$data = $repository->findOneBy(['id' => $id]);
return $data->getName();
}
public function handle()
{
parent::handle();
$item = getVal('moved_item');
if (!empty($item)) {
$this->saveList($item, 'delivery_type_delivery', 'position');
exit('{}');
}
}
public function getQuery()
{
$qb = sqlQueryBuilder()->select('dtd.*, COALESCE(dtd.name_admin, dtd.name) AS name_admin', 'dtd.id', 'dtd.name')
->from('delivery_type_delivery', 'dtd')
->orderBy('dtd.position');
$name = getVal('name');
if (isset($name) && $name) {
$qb->andWhere('dtd.name_admin LIKE :name_admin')->setParameter('name_admin', '%'.$name.'%');
}
$nameCart = getVal('nameCart');
if (isset($nameCart) && $nameCart) {
$qb->andWhere('dtd.name LIKE :name')->setParameter('name', '%'.$nameCart.'%');
}
$delivery = getVal('id_delivery');
if ($delivery) {
$qb->andWhere(Invert::checkInvert(Operator::inStringArray($delivery, 'dtd.class'), getVal('id_delivery_invert')));
}
$country = getVal('country');
if ($country) {
$operator = array_map(function ($value) {
return JsonOperator::search('dtd.data', $value, 'one', '$.restrictions.countries');
}, $country);
$qb->andWhere(Invert::checkInvert(Operator::orX($operator), getVal('country_invert')));
}
return $qb;
}
}

View File

@@ -0,0 +1,123 @@
<?php
use KupShop\AdminBundle\AdminList\BaseList;
use KupShop\AdminBundle\Query\Invert;
use KupShop\KupShopBundle\Query\JsonOperator;
use KupShop\KupShopBundle\Util\Price\Price;
use KupShop\KupShopBundle\Util\Price\PriceCalculator;
use Query\Operator;
class DeliveryList extends BaseList
{
protected $tableDef = [
'id' => 'id',
'fields' => [
'Doprava' => ['field' => 'delivery'],
'Platba' => ['field' => 'payment'],
'Cena s DPH' => ['field' => 'price', 'render' => 'renderPriceWithVat', 'class' => 'right'],
'DPH' => ['field' => 'vat', 'render' => 'renderVat'],
'Nezapočítat od' => ['field' => 'price_dont_countin_from', 'render' => 'renderPrice', 'class' => 'right'],
'Zobrazit' => ['field' => 'figure', 'render' => 'renderBoolean'],
],
];
private $priceUtil;
public function __construct()
{
$this->priceUtil = \KupShop\KupShopBundle\Util\Compat\ServiceContainer::getService(\KupShop\KupShopBundle\Util\Price\PriceUtil::class);
}
public function renderVat($values, $column)
{
return getVat($values['vat']).'%';
}
public function renderPriceWithVat($values, $column)
{
if ($values['calc_price']) {
$deliveryTypePrice = new Price(
toDecimal($values['calc_price']),
$this->priceUtil->getCurrencyById($values['currency']),
getVat($values['vat'])
);
} else {
$deliveryPrice = new Price(
toDecimal($values['delivery_price']),
$this->priceUtil->getCurrencyById($values['delivery_price_currency']),
getAdminVat()['value']
);
$paymentPrice = new Price(
toDecimal($values['payment_price']),
$this->priceUtil->getCurrencyById($values['payment_price_currency']),
getAdminVat()['value']
);
$deliveryTypePrice = PriceCalculator::add($deliveryPrice, $paymentPrice);
}
$price = PriceCalculator::convert($deliveryTypePrice, $this->priceUtil->getCurrencyById($values['currency']));
$value = printPrice($price->getPriceWithVat(), ['currency' => $price->getCurrency()]);
if ($values['calc_price']) {
return \KupShop\KupShopBundle\Util\HtmlBuilder\HTML::create('abbr')
->attr('title', 'Cena je předefinovaná u způsobu doručení')
->text($value);
} else {
return $value;
}
}
public function getQuery()
{
$qb = sqlQueryBuilder()
->select('dt.id',
'COALESCE(dt.price, dtp.price + dtd.price) as price',
'dt.price as calc_price',
'figure',
'dt.currency',
'vat',
'COALESCE(dtp.name_admin, dtp.name) as payment',
'COALESCE(dtd.name_admin, dtd.name) as delivery',
'dtd.price as delivery_price',
'dtd.currency as delivery_price_currency',
'dtp.price as payment_price',
'dtp.currency as payment_price_currency',
'dt.price_dont_countin_from',
'dtd.position * 1000 + dtp.position as list_order')
->from('delivery_type', 'dt')
->leftJoin('dt', 'delivery_type_delivery', 'dtd', 'dt.id_delivery = dtd.id')
->leftJoin('dt', 'delivery_type_payment', 'dtp', 'dt.id_payment = dtp.id')
->orderBy('dtd.position, dtp.position');
$payments = getVal('payment');
if ($payments) {
$qb->andWhere(Invert::checkInvert(Operator::inStringArray($payments, 'dtp.id'), getVal('payment_invert')));
}
$delivery = getVal('delivery');
if ($delivery) {
$qb->andWhere(Invert::checkInvert(Operator::inStringArray($delivery, 'dtd.id'), getVal('delivery_invert')));
}
$figure = getVal('figure');
if ($figure) {
$qb->andWhere(Operator::equals(['figure' => $figure]));
}
$country = getVal('country');
if ($country) {
$opDel = array_map(function ($value) {
return JsonOperator::search('dtd.data', $value, 'one', '$.restrictions.countries');
}, $country);
$opPay = array_map(function ($value) {
return JsonOperator::search('dtp.data', $value, 'one', '$.restrictions.countries');
}, $country);
$arrayMerge = array_merge($opDel, $opPay);
$qb->andWhere(Invert::checkInvert(Operator::orX($arrayMerge), getVal('country_invert')));
}
return $qb;
}
}

View File

@@ -0,0 +1,70 @@
<?php
use KupShop\AdminBundle\AdminList\BaseList;
use KupShop\AdminBundle\Query\Invert;
use Query\Operator;
class DeliveryPaymentList extends BaseList
{
use AdminListSortable;
protected $template = 'listSortable.tpl';
protected $tableDef = [
'id' => 'id',
'fields' => [
'Pořadí' => ['field' => 'position', 'render' => 'renderPosition', 'size' => 0.13],
'Název' => ['field' => 'name_admin'],
'Název v košíku' => ['field' => 'name', 'visible' => 'N'],
'Cena s DPH' => ['field' => 'price', 'render' => 'renderPriceVat'],
'Typ platby' => ['field' => 'class', 'render' => 'renderPaymentClass'],
],
];
public function renderPaymentClass($values, $column)
{
$value = $this->getListRowValue($values, $column['field']);
if (!$value) {
return $value;
}
$class = Payment::getClass($value);
if (!$class) {
return '';
}
return $class->getName();
}
public function handle()
{
parent::handle();
$item = getVal('moved_item');
if (!empty($item)) {
$this->saveList($item, 'delivery_type_payment', 'position');
exit('{}');
}
}
public function getQuery()
{
$qb = sqlQueryBuilder()->select('*, COALESCE(name_admin, name) AS name_admin', 'id')
->from('delivery_type_payment')
->orderBy('position');
$name = getVal('paymentName');
if ($name) {
$qb->andWhere(Invert::checkInvert(Operator::inStringArray($name, 'id'), getVal('paymentName_invert')));
}
$type = getVal('paymentType');
if ($type) {
$qb->andWhere(Invert::checkInvert(Operator::inStringArray($type, 'class'), getVal('paymentType_invert')));
}
return $qb;
}
}

View File

@@ -0,0 +1,152 @@
<?php
use KupShop\AdminBundle\AdminList\BaseList;
use KupShop\AdminBundle\AdminList\FiltersStorage;
class InventoryList extends BaseList
{
use FiltersStorage;
protected $tableDef = [
'id' => 's.id',
'fields' => [
'ID' => ['field' => 's.id'],
'Pozice ve skladu' => ['field' => 's.name'],
'Hotovo' => ['field' => 'finished', 'render' => 'renderBoolean', 'size' => 0.5],
'Poznámka' => ['field' => 's.note', 'size' => 2],
'Datum aplikace' => ['field' => 'date_apply', 'render' => 'renderDatetime', 'size' => 0.5],
],
];
public function getQuery()
{
$qb = sqlQueryBuilder()
->select('s.id', 's.ID', 's.name', 'IF(s.finished,"Y","N") as finished', 's.note', 's.date_apply')
->from('inventory', 's');
extract($_GET, EXTR_SKIP | EXTR_REFS);
// ###########
if (!empty($IDs)) {
$qb->andWhere(\Query\Operator::equals(['s.id' => $IDs, 's.name' => $IDs], 'OR'));
}
// ###########
if (!empty($IDpv)) {
list($IDp, $IDv) = explode(':', $IDpv);
}
// ###########
if (!empty($IDp)) {
$qb->leftJoin('s', 'inventory_items', 'si', 'si.id_inventory=s.id')
->leftJoin('si', 'products', 'p', 'si.id_product=p.id')
->leftJoin('p', 'vats', 'v', 'p.vat=v.id');
if (!empty($IDv)) {
$qb->andWhere(\Query\Operator::equals(['si.id_variation' => $IDv]));
}
$qb->andWhere(\Query\Operator::equals(['si.id_product' => $IDp]));
}
// ###########
if (!empty($name)) {
$qb->andWhere(\Query\Operator::equals(['s.name' => $name]));
}
return $qb;
}
public function handleCleanProducts()
{
sqlQuery('TRUNCATE TABLE inventory_items');
$this->returnOK('Produkty na všech pozicích byly smazány');
}
public function handleCleanAll()
{
sqlQuery('DELETE FROM inventory');
$this->returnOK('Všechny pozice byly odstraněny');
}
public function handleApplyToProducts()
{
$changeCount = 0;
sqlQuery('DROP TABLE IF EXISTS tmp_inventory');
sqlQuery("CREATE TABLE tmp_inventory
SELECT p.id id_product, pv.id id_variation, COALESCE(SUM(ii.quantity),0) quantity, GROUP_CONCAT(DISTINCT i.name ORDER BY i.name SEPARATOR ',') position
FROM products p
LEFT JOIN products_variations pv ON p.id=pv.id_product
LEFT JOIN inventory_items ii ON ii.id_product = p.id AND ((pv.id IS NULL AND ii.id_variation IS NULL) OR (ii.id_variation = pv.id))
LEFT JOIN inventory i ON ii.id_inventory=i.id
GROUP BY p.id, pv.id");
sqlQuery('ALTER TABLE tmp_inventory ADD INDEX ( `id_product` )');
sqlQuery('ALTER TABLE tmp_inventory ADD INDEX ( `id_variation` )');
sqlStartTransaction();
$notPacked = ' ('.join(', ', getStatuses('notpacked')).') ';
$pNote = '';
$vNote = '';
if (findModule('products', 'note')) {
$pNote = ', p.note=COALESCE(ti.position, p.note)';
$vNote = ', pv.note=COALESCE(ti.position, pv.note)';
}
$SQL = sqlQuery("UPDATE products p
LEFT JOIN products_variations pv ON p.id=pv.id_product
LEFT JOIN tmp_inventory ti ON ti.id_product = p.id AND ti.id_variation IS NULL
SET p.in_store = COALESCE(ti.quantity, 0) - COALESCE((
SELECT COALESCE(SUM(pieces), 0)
FROM order_items oi
LEFT JOIN orders o ON oi.id_order = o.id
WHERE o.status IN {$notPacked} AND o.status_storno=0 AND oi.id_product = p.id AND oi.id_variation IS NULL
), 0){$pNote}
WHERE pv.id IS NULL");
$changeCount += sqlAffectedRows($SQL);
$SQL = sqlQuery("UPDATE products p
LEFT JOIN products_variations pv ON p.id=pv.id_product
LEFT JOIN tmp_inventory ti ON ti.id_product = p.id AND ti.id_variation = pv.id
SET pv.in_store = COALESCE(ti.quantity, 0) - COALESCE((
SELECT COALESCE(SUM(pieces), 0)
FROM order_items oi
LEFT JOIN orders o ON oi.id_order = o.id
WHERE o.status IN {$notPacked} AND o.status_storno=0 AND oi.id_product = p.id AND oi.id_variation = pv.id
), 0){$vNote}
WHERE pv.id IS NOT NULL");
$changeCount += sqlAffectedRows($SQL);
Variations::recalcInStore();
// Warehouse bundle - propagate to positions
if (findModule(\Modules::WAREHOUSE)) {
$wrongPositions = array_column(sqlQuery('SELECT name FROM inventory i LEFT JOIN warehouse_positions wp ON wp.code = i.name WHERE wp.id IS NULL')->fetchAll(), 'name');
if ($wrongPositions) {
$this->returnError('Nemůžu najít pozici ve skladu k těmto pozicím v inventuře: '.join(', ', $wrongPositions));
}
sqlQuery('DELETE FROM warehouse_products');
sqlQuery('INSERT INTO warehouse_products (id_product, id_variation, id_position, pieces)
SELECT ii.id_product, ii.id_variation, wp.id, SUM(ii.quantity)
FROM inventory_items ii
LEFT JOIN inventory i ON ii.id_inventory = i.id
LEFT JOIN warehouse_positions wp ON wp.code = i.name
GROUP BY ii.id_product, ii.id_variation, wp.id;');
}
sqlQueryBuilder()->update('inventory')->set('date_apply', 'NOW()')->execute();
addActivityLog(\KupShop\AdminBundle\Util\ActivityLog::SEVERITY_SUCCESS, \KupShop\AdminBundle\Util\ActivityLog::TYPE_CHANGE, "Proběhla aplikace inventury. Aktualizováno {$changeCount} položek. ");
sqlFinishTransaction();
$ErrStr = "Byl aktualizován stav {$changeCount} položek";
$this->returnOK($ErrStr);
}
}

View File

@@ -0,0 +1,90 @@
<?php
use KupShop\AdminBundle\AdminList\BaseList;
class InventoryMissingList extends BaseList
{
protected $pageDivide = 500;
protected $tableDef = [
'id' => 's.id',
'fields' => [
'Název produktu' => ['field' => 'title'],
'EAN|Kód|Pozice' => ['field' => 'notes'],
'Na webu' => ['field' => 'in_store_web', 'size' => 0.5],
'Celkem inventura' => ['field' => 'in_store_inventory', 'size' => 0.5],
'Rozdíl' => ['field' => 'diff', 'size' => 0.5],
'Rozdíl cena' => ['field' => 'price_diff', 'size' => 0.5],
],
];
public function getQuery()
{
$qb = sqlQueryBuilder();
$noteField = '""';
if (findModule(Modules::PRODUCTS, Modules::SUB_NOTE)) {
$noteField = 'COALESCE(pv.note, p.note, "")';
}
$codeField = 'COALESCE(p.code, "")';
if (findModule(Modules::PRODUCTS_VARIATIONS, Modules::SUB_CODE)) {
$codeField = 'COALESCE(pv.code, p.code, "")';
}
$qb->select('id', 'title', 'notes', 'in_store_web', 'in_store_inventory', '(in_store_web-in_store_inventory) as diff', '((in_store_web-in_store_inventory)*price) as price_diff')
->from('
(SELECT CONCAT_WS(":", p.id, pv.id) id, CONCAT_WS(" ", p.title, pv.title) title,
(COALESCE(pv.in_store, p.in_store)+(
SELECT COALESCE(SUM(pieces), 0)
FROM `order_items` oi
LEFT JOIN `orders` o ON oi.id_order = o.id
WHERE o.status IN ('.join(',', getStatuses('notpacked')).') AND ((oi.id_variation = pv.id) OR (pv.id IS NULL AND oi.id_product = p.id))
)) as in_store_web,
(
SELECT COALESCE(SUM(ii.quantity),0)
FROM `inventory_items` ii
WHERE ((ii.id_variation = pv.id) OR (pv.id IS NULL AND ii.id_product = p.id))
) as in_store_inventory, COALESCE(p.price, pv.price) price, CONCAT_WS(" | ", COALESCE(pv.ean, p.ean, ""), '.$codeField.', '.$noteField.') as notes
FROM products p
LEFT JOIN products_variations pv ON p.id=pv.id_product
HAVING in_store_web<>in_store_inventory) t
');
extract($_GET, EXTR_SKIP | EXTR_REFS);
// ###########
if (!empty($IDs)) {
$qb->andWhere('(s.id=:id OR s.name=:name)')
->setParameters([
'id' => $IDs,
'name' => $IDs,
]);
}
// ###########
if (!empty($IDp)) {
global $dbcfg;
$qb->leftJoin('s', 'inventory_items', 'si', 'si.id_inventory=s.id')
->leftJoin('si', 'products', 'p', 'si.id_product=p.id')
->leftJoin('p', 'vats', 'v', 'si.id_product=p.id');
if (!empty($IDv)) {
$qb->andWhere(\Query\Operator::equals(['si.id_variation' => $IDv]));
}
$column = ['Cena produktu' => ['field' => 'si.price', 'size' => 1.5, 'class' => 'right'],
'Cena produktu DPH' => ['field' => 'si.price', 'size' => 1.8, 'class' => 'right'], ];
$this->tableDef = array_merge(array_slice($this->tableDef, 0, 3), $column, array_slice($this->tableDef, 3));
$fields = $qb->getQueryPart('select');
$fields = str_replace('ss.name, ', "ss.name, CONCAT(ROUND(si.price), ' {$dbcfg['currency']}'), CONCAT(ROUND(si.price*(1+v.vat/100)), ' {$dbcfg['currency']}'), ", $fields);
$qb->select($fields);
$qb->andWhere('si.id_product=:id_product')->setParameter('id_product', $IDp)->groupBy('s.id');
}
// ###########
if (!empty($name)) {
$qb->andWhere('s.name=:name')->setParameter('name', $name);
}
return $qb;
}
}

231
admin/lists/MenuList.php Normal file
View File

@@ -0,0 +1,231 @@
<?php
use KupShop\AdminBundle\AdminList\BaseList;
use KupShop\ContentBundle\Util\MenuUtil;
use KupShop\KupShopBundle\Util\HtmlBuilder\HTML;
class MenuList extends BaseList
{
protected $template = 'list/menu.tpl';
protected $pageDivide = 0;
protected $tableDef = [
'id' => 'id',
'fields' => [
'Název' => ['field' => 'name', 'render' => 'renderTitle', 'class' => 'nameContainer', 'size' => 3],
'Kód' => ['field' => 'code', 'render' => 'renderCode', 'size' => 2],
'Adresa odkazu' => ['field' => 'link', 'render' => 'renderUrl', 'class' => 'typeAndLinkContainer', 'size' => 3],
'Příznak' => ['field' => 'flags', 'render' => 'renderFlags', 'class' => 'columnCampaigns', 'size' => 1],
'Tlačítka' => ['field' => '', 'render' => 'renderButtons', 'class' => 'alignRight hidden-label overflow-visible hiddenTooltip', 'size' => 1.3],
],
];
public function renderUrl($values)
{
$result = HTML::create('span')->class('d-flex align-center');
$result->tag('span')->class(MenuUtil::$TYPES_CLASSES[$values['type']].' m-r-1')
->attr('title', MenuUtil::$TYPES_TITLES[$values['type']]);
$result->text(ltrim($values['url'] ?: $values['link'] ?: '', '/'));
return $result;
}
public function renderTitle($values, $column)
{
return [
HTML::create('span')
->class('drag-drop-mover')
->tag('i')
->class('bi bi-arrows-move handle')
->end(),
HTML::create('span')
->class('bi bi-dash-circle opener '
.(count($values['submenu']) > 0 ? '' : 'disabled')),
HTML::create('strong')
->attr('class', 'text-dark')
->text($this->getListRowValue($values, $column['field'])),
];
}
public function renderCode($values, $column)
{
$text = HTML::create('span');
if (isSuperuser() && $values['code'] ?? false) {
$label = ' ['.$values['code'].']';
$text->text($label)->end();
}
return $text->end();
}
public function renderFlags($values, $column)
{
$result = [];
if ($values['show_in_search'] === 'N') {
array_push($result, $this->renderBadge(translate('showInSearchN', 'menulinks'), 'badge-pastel-default', 'incognito'));
}
if ($values['figure'] === 'N') {
array_push($result, $this->renderBadge(translate('figureN', 'menulinks'), 'badge-pastel-default', 'eye-slash-fill'));
}
return $result;
}
public function renderButtons($values, $column)
{
$editBtn = HTML::create('a')->class('btn btn-primary btn-sm')
->attr('style', 'visibility:hidden')->attr('href', '#')
->tag('span')->class('bi bi-pencil-square')->end();
if ($values['type'] == MenuUtil::TYPE_PAGE) {
$editBtn = HTML::create('a')->class('btn btn-primary btn-sm')
->attr('href', '/'.ltrim($values['url'] ?? '', '/').'?inlineEditable=1')
->attr('target', '_blank')
->tag('span')->class('bi bi-pencil-square')->end();
}
$newItemBtn = HTML::create('div')->class('dropdown');
$ul = $newItemBtn->tag('a')->class('dropdown-toggle btn btn-sm btn-success')
->id('newItemDropdown_'.$values['id'])
->attr('title', translate('nestNewItem', 'menulinks'))
->attr('data-toggle', 'dropdown')
->tag('span')->class('bi bi-plus-lg')->end()
->end()
->tag('ul')->class('dropdown-menu dropdown-menu-right');
foreach (MenuUtil::$TYPES as $typeID => $name) {
$ul->tag('li')->tag('a')
->attr('href', "javascript:nw('menu', '0', '{$values['id_menu']}&data[type]={$typeID}&data[parent]={$values['id']}');")
->tag('span')->class(MenuUtil::$TYPES_CLASSES[$typeID])->end()
->text(' '.translate('add'.$name, 'menulinks'))
->end()->end(); // end a, end li
}
return [
$editBtn,
$newItemBtn,
];
}
public function createTreeMenuLinks($parentID, $level = 0)
{
if ($level > 20) {
exit('Rekurze');
}
$ret = [];
$qb = sqlQueryBuilder()->select('*')->from('menu_links', 'ml');
if (is_null($parentID)) {
$qb->where('ml.parent IS NULL AND ml.id_menu IS NULL');
} else {
$qb->where('ml.parent = :parent')->setParameter('parent', $parentID);
}
$SQL = $qb->orderBy('ml.list_order', 'ASC')->execute();
foreach ($SQL as $row) {
$row['level'] = $level;
// vytvoreni podsekci
$row['submenu'] = $this->createTreeMenuLinks($row['id'], $level + 1);
$ret[] = $row;
}
sqlFreeResult($SQL);
return $ret;
}
public function handleDrag()
{
$tree = getVal('tree');
$menuID = getVal('menuID');
if ($tree) {
$tree['position'] = (int) getVal('position', $tree);
$tree['id'] = (int) getVal('id', $tree);
if (!empty($tree['target'])) {
$target = (int) getVal('target', $tree);
$where = "parent = {$target}";
$where_insert = "parent = {$target}";
} else {
$target = null;
$where = 'parent IS NULL';
$where_insert = 'parent = NULL';
}
if ($menuID === 'null') {
$menuID = null;
$menuToSave = 'null';
$whereMenuID = 'id_menu IS NULL';
} else {
$menuToSave = $menuID = (int) $menuID;
$whereMenuID = "id_menu={$menuID}";
}
$old_parent = returnSQLResult('SELECT parent FROM '.getTableName('menu_links')." WHERE id={$tree['id']}");
sqlQuery("UPDATE menu_links SET list_order=list_order+1 WHERE {$where} AND {$whereMenuID} AND list_order >= {$tree['position']}");
sqlQuery("UPDATE menu_links SET {$where_insert}, id_menu={$menuToSave}, list_order={$tree['position']} WHERE id={$tree['id']}");
// fix id_menu for nested items in the dragged item
$parentIDsBuffer = [$tree['id']];
while ($tmpParentID = array_pop($parentIDsBuffer)) {
$result = sqlQueryBuilder()->select('id')->from('menu_links')
->where('parent=:parent')->setParameter('parent', $tmpParentID)->execute();
foreach ($result as $row) {
array_push($parentIDsBuffer, $row['id']);
}
$this->updateSQL('menu_links', ['id_menu' => $menuID], ['parent' => $tmpParentID]);
}
MenuUtil::fixOrderTreeLevelPositions($target, $menuID);
if ($old_parent != $tree['target']) {
MenuUtil::fixOrderTreeLevelPositions($old_parent, is_null($old_parent) ? null : $menuID);
}
clearCache('menu', true);
exit('OK');
}
exit('Err');
}
public function getSQL(Query\QueryBuilder $qb)
{
$data = parent::getSQL($qb);
$menu = [];
foreach (MenuUtil::getMenuRoots() as $row) {
$row['level'] = 0;
$row['submenu'] = $this->createTreeMenuLinks($row['id']);
$menu[$row['id']] = $row;
}
$menu[null] = [
'name' => translate('unclassifiedItems', 'menulinks'),
'level' => 0,
'submenu' => $this->createTreeMenuLinks(null),
];
$data['SQL'] = [
'menu' => $menu,
'menuItemTypes' => MenuUtil::$TYPES,
'menuItemTypesClasses' => MenuUtil::$TYPES_CLASSES,
];
return $data;
}
public function getQuery()
{
$qb = sqlQueryBuilder()
->select('id', 'name, link', 'target', 'list_order', 'id_menu')
->from('menu_links')
->orderBy('id_menu ASC, list_order ASC');
return $qb;
}
}

35
admin/lists/NewsList.php Normal file
View File

@@ -0,0 +1,35 @@
<?php
use KupShop\AdminBundle\AdminList\BaseList;
class NewsList extends BaseList
{
protected $tableDef = [
'id' => 'a.id',
'fields' => [
'Nadpis' => ['field' => 'a.title', 'size' => 2.5],
'Číslo' => ['field' => 'a.id', 'size' => 0.5],
'Zobrazovat novinku' => ['field' => 'a.figure', 'render' => 'renderBoolean', 'size' => 1],
'Zobrazen' => ['field' => 'a.seen', 'render' => 'renderSeen', 'size' => 0.5],
'Datum přidání' => ['field' => 'datef', 'raw_field' => 'date', 'size' => 1.5],
],
];
public function renderSeen($values, $column)
{
$value = $this->getListRowValue($values, $column['field']);
return "{$value}x";
}
public function getQuery()
{
$qb = sqlQueryBuilder()
->select('a.id', 'a.title', 'DATE_FORMAT(a.date,\''.$GLOBALS['dbcfg']['date_format'].' '.$GLOBALS['dbcfg']['time_format'].'\') AS datef', 'a.figure', 'a.type', 'a.seen')
->from('articles AS a , articles_relation AS ar')
->where('a.id=ar.id_art')
->andWhere('ar.id_branch=2');
return $qb;
}
}

View File

@@ -0,0 +1,333 @@
<?php
use KupShop\AdminBundle\AdminList\BaseList;
use KupShop\AdminBundle\AdminList\FiltersStorage;
use KupShop\AdminBundle\Query\Invert;
use KupShop\BankAutoPaymentBundle\PaymentSources\FioBankApi;
use KupShop\CatalogBundle\Query\Search;
use KupShop\KupShopBundle\Context\CurrencyContext;
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
use KupShop\KupShopBundle\Util\Contexts;
use KupShop\KupShopBundle\Util\HtmlBuilder\HTML;
use Query\Operator;
use Query\Order;
class OrderPaymentList extends BaseList
{
use FiltersStorage;
protected $tableName = 'order_payments';
protected ?string $tableAlias = 'op';
protected bool $useLazyNumberOfPages = true;
protected $template = 'list/orderPayment.tpl';
protected $pageDivide = 1000;
protected $orderParam = [
'sort' => 'ID',
'direction' => 'DESC',
];
protected $showAddItem = 'data[id_order]={ID}';
protected $tableDef = [
'id' => 'op.id',
'fields' => [
'ID' => ['field' => 'op.id', 'size' => 1],
'date' => ['translate' => true, 'field' => 'op.date', 'spec' => 'UNIX_TIMESTAMP(op.date) AS date', 'size' => 1.7, 'render' => 'renderTimestamp'],
'orderNo' => ['translate' => true, 'field' => 'o.order_no', 'size' => 1, 'type' => 'order', 'type_id' => 'id_order'],
'price' => ['translate' => true, 'field' => 'op.price', 'render' => 'renderPrice', 'class' => 'getPriceClass', 'size' => 1.2],
'note' => ['translate' => true, 'field' => 'op.note', 'size' => 3],
'transactionID' => ['translate' => true, 'field' => 'op.payment_data', 'size' => 2, 'render' => 'renderTransactionID', 'visible' => 'N'],
'admin' => ['translate' => true, 'field' => 'op.admin', 'spec' => [], 'size' => 1],
'status' => ['translate' => true, 'field' => 'op.status', 'size' => 0.8, 'render' => 'renderNotBool'],
'gate' => ['translate' => true, 'field' => 'gate', 'render' => 'renderSentToGate', 'size' => 0.8],
'return' => ['translate' => true, 'render' => 'renderReturn', 'size' => 1.2],
'paymentType' => ['translate' => true, 'field' => 'method', 'render' => 'renderPaymentType', 'visible' => 'N'],
],
];
public function getQuery()
{
$qb = parent::getQuery();
$qb->leftJoin('op', 'orders', 'o', 'o.id=op.id_order')->addSelect('o.order_no');
if (findModule(\Modules::CURRENCIES)) {
$qb->addSelect('o.currency');
}
return $qb;
}
public function customizeTableDef($tableDef)
{
$tableDef = parent::customizeTableDef($tableDef);
$tableDef['fields']['admin']['spec'] = function (Query\QueryBuilder $qb) {
$qb->leftJoin('op', 'admins', 'a', 'op.admin=a.id');
$qb->addSelect('a.login as admin');
};
if (findModule(\Modules::EET)) {
$tableDef['fields'] += [
'EET FIK' => ['field' => 'fik', 'size' => 2, 'spec' => function (Query\QueryBuilder $qb) {
$qb->leftJoin('op', 'eet_sent_payment', 'esp', 'esp.id_payment = op.id');
$qb->addSelect('esp.fik');
}],
];
}
if (getVal('window')) { // platby 1 konkretni objednavky
$tableDef['fields']['orderNo']['visible'] = 'N';
}
return $tableDef;
}
// price nechceme zaokrouhlovat = zobrazit jak je ulozena
public function renderFormatPrice($values, $column)
{
$value = $this->renderCell($values, $column);
$params = [
'printcurrency' => false,
'ceil' => false,
'decimal' => 'dynamic',
];
$currency = Contexts::get(CurrencyContext::class)->getOrDefault($values['currency'] ?? null);
$params['currency'] = $currency;
return [
printPrice($value, $params).' ',
HTML::create('span')->class('currency')->text($currency->getSymbol()),
];
}
public function renderPaymentType($values, $column)
{
if (empty($values['method'])) {
return '';
}
$paymentListTypes = translate('types', 'orderPayment');
$paymentListTypesPOS = translate('typesPOS', 'orderPayment');
return $paymentListTypes[$values['method']] ?? $paymentListTypesPOS[$values['method']] ?? '';
}
public function renderReturn($values, $column)
{
if ($values['price'] < 0) {
return '';
}
$params = [
'data' => [
'id_order' => $values['id_order'] ?? '',
'return_payment_id' => $values['id'],
],
'autoclose' => 1,
];
$params = http_build_query($params);
return [
HTML::create('a')
->attr('href', "javascript:nw('orderPayment', 0, '{$params}');")
->class('btn btn-xs btn-primary')
->attr('title', 'Vrátit platbu')
->text('Vrátit')
->end(),
HTML::create('input')
->attr('type', 'hidden')
->attr('name', 'orders[]')
->attr('value', $values['id_order'] ?? '')
->attr('style', 'margin: 0 5px 0 0; float:left;')
->attr('checked', 'checked'),
];
}
public function renderID($values, $column)
{
$order_no = $this->getListRowValue($values, 'order_no');
$id_order = $this->getListRowValue($values, 'id');
return "<input type='checkbox' name='orders[]' value='{$id_order}' style='margin: 0 5px 0 0; float:left;' checked='checked'>
<a href=\"javascript:nw('orders', '{$id_order}', 'refresh=noopener');\">{$order_no}</a>";
}
public function renderNotBool($values, $column)
{
$tooltip = translate('statuses', 'orderPayment')[$values['status']] ?? $values['status'];
return $this->renderBoolean(['status' => !$values['status']], $column, $tooltip);
}
public function renderSentToGate($values, $column)
{
$data = json_decode($values['payment_data'] ?? '{}', true);
return $this->renderBoolean(['gate' => !empty($data['session'])], $column);
}
public function renderTimestamp($values, $column)
{
$timestamp = $this->getListRowValue($values, $column['field']);
$days = ['Pondělí', 'Úterý', 'Středa', 'Čtvrtek', 'Pátek', 'Sobota', 'Neděle'];
return $days[date('N', $timestamp) - 1].' '.date('j.n.Y H:i:s', $timestamp);
}
public function renderTransactionID($values, $column)
{
$payment_data = $this->getListRowValue($values, $column['field']);
if (empty($payment_data)) {
return '';
}
$payment_data = json_decode($payment_data, true);
return $payment_data['transactionID'] ?? $payment_data['session'] ?? '';
}
public function getPriceClass($values)
{
if ($values['status'] != 0) {
return '';
}
return ($values['price'] > 0) ? 'text-success' : 'text-danger';
}
public function handleFioCheckPayments()
{
$fioBankApi = ServiceContainer::getService(FioBankApi::class);
if (!$fioBankApi->runCheckPayments()) {
$this->returnError('Kontrola plateb selhala.');
return;
}
$this->returnOK('Operace proběhla v pořádku.');
}
public function handle()
{
parent::handle();
if (getVal('Submit')) {
$data = getVal('data');
foreach ($data['orderPayments'] as $payment) {
if (empty($payment['inserted']) && empty($payment['choosed'])) {
continue;
}
$payment['date'] = date('Y-m-d H:i:s');
if (!empty($payment['inserted'])) {
$payment['price'] = $payment['inserted'];
} elseif (!empty($payment['choosed'])) {
$payment['price'] = $payment['choosed'] * (-1);
}
if (!empty($payment['price'])) {
$payment['method'] = ($payment['price'] > 0) ? 4 : 5;
}
$this->insertSQL('order_payments', ['price' => $payment['price'], 'date' => $payment['date'], 'note' => $payment['note'], 'id_order' => null, 'method' => $payment['method']]);
}
}
}
public function getFilterQuery(): Query\QueryBuilder
{
$qb = parent::getFilterQuery();
if ($dateFrom = $this->prepareDate(getVal('dateFrom'))) {
$dateFrom .= ' 00:00:00';
}
if ($dateTo = $this->prepareDate(getVal('dateTo'))) {
$dateTo .= ' 23:59:59';
}
if (!empty($dateFrom) || !empty($dateTo)) {
$qb->andWhere(Operator::between('op.date', new Range($dateFrom, $dateTo)));
}
$priceFrom = getVal('priceFrom');
$this->preparePrice($priceFrom);
$priceTo = getVal('priceTo');
$this->preparePrice($priceTo);
if ($priceFrom || $priceTo) {
$qb->andWhere(Operator::between('op.price', new Range($priceFrom, $priceTo)));
}
if ($direction = getVal('direction')) {
$spec = [];
foreach ($direction as $dir) {
$spec[] = ($dir == 'incoming' ? 'op.price > 0' : 'op.price < 0');
}
$qb->andWhere(Operator::orX($spec));
}
if ($types = getVal('types')) {
$qb->andWhere(Invert::checkInvert(Operator::inIntArray($types, 'op.method'), getVal('types_invert')));
}
if ($status = getVal('status')) {
$qb->andWhere(Invert::checkInvert(Operator::inIntArray($status, 'op.status'), getVal('status_invert')));
}
if ($admins = getVal('admins')) {
$qb->andWhere(Invert::checkInvert(Operator::inIntArray($admins, 'op.admin'), getVal('admins_invert')));
}
if ($pos = getVal('pos')) {
$qb->join('op', 'pos_payments_relation', 'ppr', 'ppr.id_payment = op.id')
->andWhere(Invert::checkInvert(Operator::inIntArray($pos, 'ppr.id_pos'), getVal('pos_invert')));
}
if ($ID = getVal('ID')) { // ID objednavky
$qb->andWhere(Operator::equals(['op.id_order' => $ID]));
}
if ($idCode = getVal('idCode')) { // Čísla / kódy objednávek
$idCode = str_replace(',', ' ', $idCode);
$searchFields = [
['field' => 'o.user_order_no', 'match' => 'left', 'order' => '1'],
['field' => 'o.id', 'match' => 'exact', 'order' => '1', 'match' => 'numeric'],
];
$qb->leftJoin('op', 'orders', 'o', 'o.id=op.id_order');
$qb->andWhere(Invert::checkInvert(
Operator::orX([
Search::searchFields($idCode, $searchFields, 'OR'),
Order::byOrderNo(preg_split('/[[:blank:]]+/', trim($idCode))),
]
),
getVal('idCode_invert')));
}
if ($IDs = getVal('IDs')) { // IDs plateb
$qb->andWhere(Operator::inIntArray($IDs, 'op.id'));
}
if ($note = getVal('note')) {
$qb->andWhere(Invert::checkInvert(Operator::like(['op.note' => '%'.$note.'%']), getVal('note_invert')));
}
return $qb;
}
public function get_vars()
{
$vars = parent::get_vars();
$vars['in_pos'] = sqlQueryBuilder()->select('SUM(price) as in_pos')->from('order_payments')
->where('method=1 OR method=4 OR method=5') // Jen v hotovosti = 1 - Hotově, 4 - Pokladna vklad, 5 - Pokladna výběr
->execute()->fetchOne();
if (findModule(Modules::POS) || findModule(Modules::NEW_POS)) {
if (($admins = getVal('admins')) && (count($admins) == 1) && !getVal('admins_invert')) {
$vars['specific_pos'] = reset($admins);
}
}
return $vars;
}
}

596
admin/lists/OrdersList.php Normal file
View File

@@ -0,0 +1,596 @@
<?php
use KupShop\AdminBundle\AdminList\BaseList;
use KupShop\AdminBundle\AdminList\FiltersStorage;
use KupShop\AdminBundle\Util\OrdersListFilter;
use KupShop\KupShopBundle\Context\CurrencyContext;
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
use KupShop\KupShopBundle\Util\HtmlBuilder\HTML;
use KupShop\OrderingBundle\Attachment\InvoicePDFAttachment;
use KupShop\OrderingBundle\Util\Order\OrderInfo;
use Query\Operator as Op;
$main_class = 'OrdersList';
class OrdersList extends BaseList
{
use FiltersStorage;
protected $template = 'list/orders.tpl';
protected $orderParam = [
'sort' => 'code',
'direction' => 'DESC',
];
protected $tableName = 'orders';
protected ?string $tableAlias = 'o';
protected bool $useLazyNumberOfPages = true;
protected $showMassEdit = true;
protected $tableDef = [
'id' => 'o.id',
'fields' => [
'code' => ['translate' => true, 'field' => 'o.id', 'render' => 'renderCode', 'type' => 'orders', 'size' => 0.7],
'source' => ['translate' => true, 'field' => 'o.source', 'spec' => 'o.source', 'render' => 'renderOrderSource', 'visible' => 'N'],
'customer' => ['translate' => true, 'field' => 'o.invoice_name', 'raw_field' => 'IF(o.invoice_firm != "", o.invoice_firm, o.invoice_surname)', 'render' => 'renderName', 'size' => 1.5, 'spec' => 'o.invoice_name'],
'status' => ['translate' => true, 'field' => 'o.status', 'render' => 'renderStatus', 'size' => 1, 'spec' => 'o.status', 'fieldType' => OrdersList::TYPE_LIST],
'orderItems' => ['translate' => true, 'field' => 'items', 'render' => 'renderItems', 'class' => 'left tiny-list-items', 'size' => 2, 'visible' => 'N'],
'price' => ['translate' => true, 'field' => 'o.total_price', 'render' => 'renderPrice', 'class' => 'text-right alignRight', 'size' => 1, 'headerRender' => 'renderHeaderPrice', 'spec' => 'o.total_price', 'editable' => 'N', 'fieldType' => BaseList::TYPE_PRICE],
'priceWithoutVat' => ['translate' => true, 'field' => 'o.total_price_without_vat', 'render' => 'renderPrice', 'class' => 'text-right alignRight', 'size' => 1, 'headerRender' => 'renderHeaderPrice', 'spec' => 'o.total_price_without_vat', 'editable' => 'N', 'fieldType' => BaseList::TYPE_PRICE, 'visible' => 'N'],
'delivery_type' => ['translate' => true, 'field' => 'o.delivery_type', 'render' => 'renderDelivery', 'class' => 'getDeliveryClass', 'size' => 1.25, 'spec' => []],
'delivery_name' => ['translate' => true, 'field' => 'delivery_name', 'visible' => 'N', 'spec' => []],
'payment_name' => ['translate' => true, 'field' => 'payment_name', 'visible' => 'N', 'spec' => []],
'flags' => ['translate' => true, 'field' => 'o.flags', 'render' => 'renderFlags', 'class' => 'columnCampaigns product-campaigns', 'size' => 0.7, 'spec' => [], 'fieldType' => OrdersList::TYPE_LIST_MULTISELECT],
'date' => ['translate' => true, 'field' => 'o.date_created', 'render' => 'renderDateTime', 'spec' => 'o.date_created'],
'statusPaid' => ['translate' => true, 'field' => 'status_payed', 'render' => 'renderStatusPaid', 'size' => 0.5],
'discounts' => ['translate' => true, 'render' => 'renderDiscounts', 'class' => 'left tiny-list-items', 'size' => 1, 'visible' => 'N'],
'email' => ['translate' => true, 'field' => 'o.invoice_email', 'spec' => 'o.invoice_email', 'visible' => 'N', 'fieldType' => BaseList::TYPE_STRING],
'zip' => ['translate' => true, 'field' => 'o.delivery_zip', 'spec' => 'o.delivery_zip', 'visible' => 'N', 'fieldType' => BaseList::TYPE_STRING],
'deliveryCountry' => ['translate' => true, 'field' => 'o.delivery_country', 'spec' => 'o.delivery_country', 'visible' => 'N', 'fieldType' => BaseList::TYPE_STRING],
'currency' => ['translate' => true, 'field' => 'o.currency', 'spec' => 'o.currency', 'visible' => 'N', 'fieldType' => BaseList::TYPE_STRING],
'note' => ['translate' => true, 'field' => 'o.note_user', 'spec' => 'o.note_user', 'visible' => 'N'],
'noteUser' => ['translate' => true, 'field' => 'user_note', 'spec' => 'o.invoice_email', 'render' => 'renderUserNote', 'visible' => 'N'],
'date_updated' => ['translate' => true, 'field' => 'o.date_updated', 'render' => 'renderDateTime', 'visible' => 'N'],
'date_delivered' => ['translate' => true, 'field' => 'o.date_delivered', 'render' => 'renderDateTime', 'visible' => 'N'],
'userOrderNo' => ['translate' => true, 'field' => 'o.user_order_no', 'spec' => 'o.user_order_no', 'type' => 'orders', 'visible' => 'N'],
'phone' => ['translate' => true, 'field' => 'o.invoice_phone', 'spec' => 'o.invoice_phone', 'visible' => 'N', 'fieldType' => BaseList::TYPE_STRING],
'invoiceFirm' => ['translate' => true, 'field' => 'o.invoice_firm', 'spec' => 'o.invoice_firm', 'visible' => 'N', 'fieldType' => BaseList::TYPE_STRING],
'invoiceIco' => ['translate' => true, 'field' => 'o.invoice_ico', 'spec' => 'o.invoice_ico', 'visible' => 'N', 'fieldType' => BaseList::TYPE_STRING],
'invoiceDic' => ['translate' => true, 'field' => 'o.invoice_dic', 'spec' => 'o.invoice_dic', 'visible' => 'N', 'fieldType' => BaseList::TYPE_STRING],
'invoiceZip' => ['translate' => true, 'field' => 'o.invoice_zip', 'spec' => 'o.invoice_zip', 'visible' => 'N', 'fieldType' => BaseList::TYPE_STRING],
'invoiceCountry' => ['translate' => true, 'field' => 'o.invoice_country', 'spec' => 'o.invoice_country', 'visible' => 'N', 'fieldType' => BaseList::TYPE_STRING],
'deliveryFirm' => ['translate' => true, 'field' => 'o.delivery_firm', 'spec' => 'o.delivery_firm', 'visible' => 'N', 'fieldType' => BaseList::TYPE_STRING],
'deliveryStreet' => ['translate' => true, 'field' => 'o.delivery_street', 'spec' => 'o.delivery_street', 'visible' => 'N', 'fieldType' => BaseList::TYPE_STRING],
'deliveryCity' => ['translate' => true, 'field' => 'o.delivery_city', 'spec' => 'o.delivery_city', 'visible' => 'N', 'fieldType' => BaseList::TYPE_STRING],
'deliveryPhone' => ['translate' => true, 'field' => 'o.delivery_phone', 'spec' => 'o.delivery_phone', 'visible' => 'N', 'fieldType' => BaseList::TYPE_STRING],
'customerGroups' => ['translate' => true, 'field' => 'customer_groups', 'spec' => [], 'visible' => 'N'],
'trackingNumber' => ['translate' => true, 'field' => 'package_id', 'render' => 'renderPackage', 'visible' => 'N', 'spec' => []],
'priceLevel' => ['translate' => true, 'field' => 'id', 'render' => 'renderPriceLevel', 'visible' => 'N'],
],
'class' => 'getRowClass',
];
private $orderTotalPriceSum;
/**
* @var OrdersListFilter
*/
protected $ordersListFilter;
/** @var OrderInfo */
protected $orderInfo;
public function __construct()
{
$this->orderTotalPriceSum = toDecimal(0);
$this->ordersListFilter = ServiceContainer::getService(OrdersListFilter::class);
$this->orderInfo = ServiceContainer::getService(OrderInfo::class);
}
public function getSQLOrdering(&$var, &$orderParam)
{
parent::getSQLOrdering($var, $orderParam);
if (isset($var['orderField']) && ($var['orderField'] == 'items' || $var['orderField'] == 'user_note')) {
$var['orderField'] = '';
}
}
public function customizeTableDef($tableDef)
{
$tableDef = parent::customizeTableDef($tableDef);
$cfg = \KupShop\KupShopBundle\Config::get();
$dbcfg = Settings::getDefault();
if (!findModule('eshop_delivery')) {
unset($tableDef['fields']['delivery']);
}
if (!findModule(Modules::PRICE_LEVELS)) {
unset($tableDef['fields']['priceLevel']);
}
if (empty($cfg['Order']['Flags'])) {
unset($tableDef['fields']['flags']);
}
if (findModule(Modules::TRANSLATIONS)) {
$tableDef['fields']['Jazyk'] = ['field' => 'o.id_language', 'spec' => 'o.id_language', 'visible' => 'N'];
}
if (findModule(Modules::INVOICES)) {
$tableDef['fields']['invoiceNo'] = ['translate' => true, 'field' => 'o.invoice_no', 'render' => 'renderInvoice', 'spec' => 'o.invoice_no'];
}
if (findModule(Modules::PRODUCTS, Modules::SUB_WEIGHT)) {
$tableDef['fields']['weight'] = ['translate' => true, 'field' => 'o.total_weight', 'spec' => 'o.total_weight', 'render' => 'renderFloat', 'visible' => 'N'];
}
if (findModule(Modules::DROPSHIP)) {
$tableDef['fields']['dropship'] = ['translate' => true, 'field' => 'dropship_name', 'visible' => 'N', 'render' => 'renderDropshipment', 'spec' => function (Query\QueryBuilder $qb) {
$qb->addSelect('dps.name as dropship_name, dps.id as dropship_id')
->leftJoin('o', 'order_dropshipment', 'odps', 'odps.id_order = o.id')
->leftJoin('odps', 'dropshipment', 'dps', 'dps.id = odps.id_dropshipment');
}];
}
if (findModule(Modules::BONUS_PROGRAM)) {
$tableDef['fields']['bonusPoints'] = ['translate' => true, 'field' => 'bonus_points', 'visible' => 'N', 'spec' => function (Query\QueryBuilder $qb) {
$qb->addSelect('bp.points as bonus_points')
->leftJoin('o', 'bonus_points', 'bp', 'o.id = bp.id_order');
}];
}
$tableDef['fields']['customerGroups']['spec'] = function (Query\QueryBuilder $qb) {
$qb->addSelect('GROUP_CONCAT(ug.name) as customer_groups')
->leftJoin('o', 'users_groups_relations', 'ugr', 'ugr.id_user=o.id_user')
->leftJoin('ugr', 'users_groups', 'ug', 'ug.id=ugr.id_group')
->groupBy('o.id');
};
$tableDef['fields']['payment_name']['spec'] = function (Query\QueryBuilder $qb) {
$qb->addSelect('COALESCE(dtp.name_admin, dtp.name) as payment_name')
->leftJoin('o', 'delivery_type', 'dt', 'dt.id=o.id_delivery')
->leftJoin('dt', 'delivery_type_payment', 'dtp', 'dtp.id=dt.id_payment');
};
$tableDef['fields']['trackingNumber']['spec'] = function (Query\QueryBuilder $qb) {
$qb->addSelect('o.package_id, dtd.class')
->leftJoin('o', 'delivery_type', 'dt', 'dt.id=o.id_delivery')
->leftJoin('dt', 'delivery_type_delivery', 'dtd', 'dtd.id=dt.id_delivery');
};
$tableDef['fields']['delivery_name']['spec'] = function (Query\QueryBuilder $qb) {
$qb->addSelect('COALESCE(dtd.name_admin, dtd.name) as delivery_name')
->leftJoin('o', 'delivery_type', 'dt', 'dt.id=o.id_delivery')
->leftJoin('dt', 'delivery_type_delivery', 'dtd', 'dtd.id=dt.id_delivery');
};
$tableDef['fields']['delivery_type']['spec'] = function (Query\QueryBuilder $qb) {
$qb->addSelect('COALESCE(dtp.name_admin, dtp.name) as payment_name, COALESCE(dtd.name_admin, dtd.name) as delivery_name')
->leftJoin('o', 'delivery_type', 'dt', 'dt.id=o.id_delivery')
->leftJoin('dt', 'delivery_type_payment', 'dtp', 'dtp.id=dt.id_payment')
->leftJoin('dt', 'delivery_type_delivery', 'dtd', 'dtd.id=dt.id_delivery');
};
$tableDef['fields']['dateDue'] = ['translate' => true, 'field' => 'date_due', 'render' => 'renderDate',
'spec' => 'COALESCE(o.date_due, (COALESCE(o.date_handle, o.date_accept, o.date_created) + INTERVAL '.($dbcfg->shop_due_days ?: 14).' DAY)) as date_due',
'visible' => 'N',
];
foreach (getOrderStatuses() as $statusId => $status) {
$tableDef['fields']['status']['fieldOptions'][$statusId] = $status['name'];
}
$tableDef['fields']['flags']['spec'] = function (Query\QueryBuilder $qb) {
$qb->addSelect('o.flags');
};
if (!empty($cfg['Order']['Flags'])) {
foreach ($cfg['Order']['Flags'] as $flag => $value) {
$tableDef['fields']['flags']['fieldOptions'][$flag] = $value['name'];
}
}
if (findModule(Modules::NEW_POS)) {
$tableDef['fields']['pos'] = ['field' => 'pos_name', 'translate' => true, 'size' => 1.5,
'spec' => function (Query\QueryBuilder $qb) {
$qb->addSelect('po.name AS pos_name, po.id AS pos_id')
->leftJoin('o', 'pos', 'po', 'o.pos = po.id');
}];
}
if (findModule(Modules::SELLERS)) {
$tableDef['fields']['seller'] = ['translate' => true,
'field' => 'seller_name',
'visible' => 'N',
'render' => 'renderSeller',
'spec' => function (Query\QueryBuilder $qb) {
$qb->addSelect('sell.title as seller_name, sell.id as seller_id')
->leftJoin('o', 'order_sellers', 'osell', 'osell.id_order = o.id')
->leftJoin('osell', 'sellers', 'sell', 'sell.id = osell.id_seller');
}];
}
return $tableDef;
}
public function renderInvoice(array $values): HTML
{
return HTML::create('a')
->attr('href', path('kupshop_admin_emailattachment_adminattachment', ['id_order' => $values['id'], 'type' => InvoicePDFAttachment::getType()]))
->attr('target', '_blank')
->text($values['invoice_no']);
}
public function renderDropshipment(array $values): HTML
{
return HTML::create('a')
->attr('href', 'javascript:nw(\'Dropshipment\', '.$values['dropship_id'].')')
->text($values['dropship_name']);
}
public function renderSeller(array $values): HTML
{
return HTML::create('a')
->attr('href', 'javascript:nw(\'sellers\', '.$values['seller_id'].')')
->text($values['seller_name']);
}
public function renderOrderSource(array $values): string
{
return OrderInfo::getOrderSources()[$values['source']] ?? '';
}
public function renderStatusPaid($values, $column)
{
$value = $this->renderCell($values, $column);
if (in_array($value, [Order::STATUS_OVERPAID, Order::STATUS_UNDERPAID])) {
if ($value == Order::STATUS_OVERPAID) {
$tooltip = translate('statusOverPaid', 'orders');
} else {
$tooltip = translate('statusUnderPaid', 'orders');
}
return $this->renderIcon('warning', 'Ne', $tooltip);
} else {
return $this->renderBoolean($values, $column);
}
}
public function renderPackage($values, $column)
{
if (empty($values['package_id'])) {
return '';
}
$delivery = \Delivery::getClass($values['class']);
$link = $delivery->getTrackAndTraceLink($values['package_id']) ?? '';
return HTML::create('a')
->attr('href', $link)
->attr('target', '_blank')
->text($values['package_id']);
}
public function renderUserNote($values, $column)
{
if (!empty($values['invoice_email'])) {
if ($note = $this->selectSQL('users', ['email' => $values['invoice_email']], ['note'])->fetchColumn()) {
return $note;
}
}
return '';
}
public function renderItems($values, $column)
{
$items = sqlQueryBuilder()->select('oi.descr, oi.pieces, oi.id_product, oi.id_variation')
->from('order_items', 'oi')
->where(Op::equals(['id_order' => $values['id']]))
->execute()
->fetchAll();
$output = HTML::create('span');
$idProductIn = getVal('productId');
$idProductsIn = getVal('products', default: []);
$idProductIn && $idProductsIn[] = $idProductIn;
foreach ($items as $item) {
$searchId = $item['id_product'].($item['id_variation'] ? '-'.$item['id_variation'] : '');
if ($item['id_product'] ?? false) {
$output
->tag('div')
->text(floatval($item['pieces']).'x ')
->tag('a')
->attr('href', 'javascript:nw(\'product\', \''.$item['id_product'].'\')')
->tag(in_array($searchId, $idProductsIn) || in_array($item['id_product'], $idProductsIn) ? 'strong' : 'span')
->text($item['descr'])
->end()
->end()
->end();
} else {
$output
->tag('div')
->text(floatval($item['pieces']).'x '.$item['descr'])
->end();
}
}
return $output;
}
public function renderDiscounts($values, $column)
{
$output = HTML::create('span');
$used_order_discounts = $this->orderInfo->getUsedDiscounts($values['id']);
foreach ($used_order_discounts as $id => $name) {
$output->tag('div')->tag('a')
->attr('href', "javascript:nw('OrderDiscounts', '{$id}')")
->attr('title', translate('showDiscount', 'OrderDiscounts'))
->tag('span')->class('badge badge-primary badge-light')
->text($name)
->end()->end()->end();
}
return $output;
}
public function renderDelivery($values, $column)
{
$delivery = $values['delivery_type'];
if (!empty($values['id_delivery'])) {
$delivery = $values['payment_name'].' - '.$values['delivery_name'];
}
$styles = $this->getStyles();
$delivery_class = 'delivery';
foreach ($styles as $id => $style) {
if (!empty($style['id_delivery']) && ($style['id_delivery'] == $values['id_delivery'])) {
$delivery_class = $id;
}
}
foreach ($styles as $id => $style) {
if ($style['match'] && (stripos($values['delivery_type'], $style['match']) !== false || stripos($style['match'], $values['delivery_type'] ?? '') !== false) && $style['value']) {
$delivery_class = $id;
}
}
return $this->renderBadge($delivery, 'badge-default badge-'.$delivery_class, null);
}
public function renderFlags($values, $column)
{
$cfg = \KupShop\KupShopBundle\Config::get();
$flags = $this->getListRowValue($values, $column['field']);
if (empty($flags)) {
return '';
}
$flags = preg_split('/,/', $flags);
$ret = [];
foreach (array_intersect($flags, array_keys($cfg['Order']['Flags'])) as $flag) {
$ret[] = HTML::create('span')
->class('badge badge-pastel-default')
->tag('span')->class('tooltip-text')->text($cfg['Order']['Flags'][$flag]['name'] ?? $flag)->end()
->tag('span')->class('badge-text')->text($flag)->end();
}
return $ret;
}
public function getRowClass($values)
{
$class = '';
if ($values['status_storno'] == 1) {
$class .= ' storno';
}
$class .= " status{$values['status']}";
return $class;
}
public function getDeliveryClass($values)
{
$styles = $this->getStyles();
foreach ($styles as $id => $style) {
if (!empty($style['id_delivery']) && ($style['id_delivery'] == $values['id_delivery'])) {
return 'delivery '.$id;
}
}
foreach ($styles as $id => $style) {
if ($style['match'] && (stripos($values['delivery_type'], $style['match']) !== false || stripos($style['match'], $values['delivery_type'] ?? '') !== false)) {
return 'delivery '.$id;
}
}
return 'delivery ';
}
public function renderName($values, $column)
{
$parts = [];
$name = $this->getListRowValue($values, $column['field']);
$surname = $this->getListRowValue($values, 'invoice_surname');
$company = $this->getListRowValue($values, 'invoice_firm');
if ($company) {
$parts[] = $company;
}
if ($name || $surname) {
$parts[] = join(' ', [$surname, $name]);
}
return join(', ', $parts);
}
public function renderCode($values, $column)
{
return $this->getListRowValue($values, 'order_no');
}
public function renderStatus($values, $column)
{
global $cfg;
$status = $this->getListRowValue($values, $column['field']);
if ($values['status_storno'] == 1) {
return $this->renderBadge($cfg['Order']['Status']['storno'][$values['status_storno']], 'badge-danger', null);
}
return $this->renderBadge($cfg['Order']['Status']['global'][$status], 'badge-default status-'.$status, null);
}
public function getStyles()
{
if (isset($this->styles)) {
return $this->styles;
}
$styles = [];
$qb = sqlQueryBuilder();
if (findModule('eshop_delivery')) {
$qb->select('dt.id', 'CONCAT_WS(" - ", p.name, d.name) AS name', 'dt.format')
->from(getTableName('delivery_type'), 'dt')
->leftJoin('dt', getTableName('delivery_type_delivery'), 'd', 'dt.id_delivery=d.id')
->leftJoin('dt', getTableName('delivery_type_payment'), 'p', 'dt.id_payment=p.id')
->orderBy('vat', 'ASC');
foreach ($qb->execute() as $row) {
$styles["delivery{$row['id']}"] = ['match' => $row['name'], 'id_delivery' => $row['id'], 'value' => "{$row['format']}"];
}
}
$this->styles = $styles;
return $this->styles;
}
public function get_vars()
{
/** @var \KupShop\ElninoBundle\Query\QueryBuilder $qb */
$qb = sqlQueryBuilder();
$vars = parent::get_vars();
$vars['styles'] = $this->getStyles();
$pid = getVal('productId');
$vid = getVal('variationId');
$sold = getVal('sold');
if (!empty($sold) && !empty($pid)) {
$qb->select('YEAR(o.date_created) as year', 'SUM(oi.pieces) as count')
->from(getTableName('order_items'), 'oi')
->leftJoin('oi', getTableName('orders'), 'o', 'oi.id_order=o.id')
->where('oi.id_product='.$pid.' AND o.status_storno=0')
->groupBy('YEAR(o.date_created)')
->orderBy('year', 'DESC');
if (!empty($vid)) {
$qb->andWhere(Op::equals(['oi.id_variation' => $vid]));
}
$SQL = $qb->execute();
$vars['sold'] = [];
$vars['sold_total'] = 0;
foreach ($SQL as $row) {
$vars['sold'][] = $row;
$vars['sold_total'] += $row['count'];
}
}
return $vars;
}
public function renderPrice($values, $column)
{
$totalPrice = toDecimal($values['total_price']);
if (!empty($values['currency_rate'])) {
$totalPrice = $totalPrice->mul(toDecimal($values['currency_rate']));
}
$this->orderTotalPriceSum = $this->orderTotalPriceSum->add($totalPrice);
return parent::renderPrice($values, $column);
}
// renderFormatPrice na OrdersListu se pouziva pouze pro total_price
// total_price nechceme zaokrouhlovat = zobrazit jak je ulozena na objednavce
public function renderFormatPrice($values, $column)
{
$value = $this->renderCell($values, $column);
$params = [
'printcurrency' => false,
'ceil' => false,
'decimal' => 'dynamic',
];
$currencyContext = ServiceContainer::getService(CurrencyContext::class);
$currency = $currencyContext->getActive();
if (!empty($values['currency'])) {
$currency = $currencyContext->getAll()[$values['currency']];
$params['currency'] = $currency;
}
return [
printPrice($value, $params).' ',
HTML::create('span')->class('currency')->text($currency->getSymbol()),
];
}
public function renderPriceLevel(array $values, array $column): HTML
{
$data = json_decode($values['note_admin'] ?: '', true) ?: [];
if (!empty($data['price_level']['name'])) {
return HTML::create('a')
->attr('href', 'javascript:nw(\'pricelevel\', '.$data['price_level']['id'].')')
->attr('title', $data['price_level']['name'])
->text($data['price_level']['name']);
}
return HTML::create('span')
->text('');
}
public function getTotalPriceSum()
{
return $this->orderTotalPriceSum;
}
public function getFilterQuery(): Query\QueryBuilder
{
$qb = parent::getFilterQuery();
$qb = $this->ordersListFilter->addQueryBuilderParams($qb, $_GET);
if (findModule(Modules::POS) && $qb->getQueryPart('where') == null) {
if (getVal('pos_orders')) {
$qb->andWhere('o.pos >= 1');
} else {
$qb->andWhere('o.pos = 0 OR o.pos is null');
}
}
return $qb;
}
}

View File

@@ -0,0 +1,473 @@
<?php
use KupShop\AdminBundle\AdminList\FiltersStorage;
use KupShop\AdminBundle\Util\OrdersListFilter;
use KupShop\BalikonosBundle\Balikobot;
use KupShop\KupShopBundle\Email\OrderMessageEmail;
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
use KupShop\KupShopBundle\Util\HtmlBuilder\HTML;
use PhpOffice\PhpSpreadsheet\Reader\Csv;
use PhpOffice\PhpSpreadsheet\Writer\Xls;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
use Query\Operator;
use Query\QueryBuilder;
require_once $cfg['Path']['shared_version'].'admin/lists/OrdersList.php';
class OrdersMassProcessList extends OrdersList
{
use FiltersStorage;
/**
* @var OrdersListFilter
*/
protected $ordersListFilter;
protected $template = 'list/ordersMassProcess.tpl';
protected $changeOrdersCodes = [];
protected $orderParam = [
'sort' => 'code',
'direction' => 'DESC',
];
protected $pageDivide = 500;
public function customizeTableDef($tableDef)
{
$fields = [
'customer' => ['translate' => true, 'field' => 'customer', 'render' => 'renderCustomer', 'size' => 3.5, 'translation_section' => 'orders'],
'Položek' => ['field' => 'amount', 'spec' => 'COUNT(o.id) as amount'],
'Hmotnost' => ['field' => 'weight', 'render' => 'renderWeight'],
'ČP Velikost' => ['field' => 'weight', 'render' => 'renderSize', 'class' => 'has-input'],
'Balíků' => ['field' => 'packages', 'render' => 'renderPackages', 'class' => 'has-input'],
];
if (findModule(Modules::PRODUCTS, Modules::SUB_WEIGHT)) {
$fields['Hmotnost'] = ['field' => 'o.total_weight', 'spec' => 'o.total_weight', 'render' => 'renderWeight', 'class' => 'has-input'];
}
if (findModule('balikonos', 'provider') == 'balikobot') {
$dbcfg = Settings::getDefault();
$balikobotSettings = $dbcfg['balikobot']['delivery_type'] ?? [];
$balikobotSettings = array_combine(array_keys($balikobotSettings), array_column($balikobotSettings, 'carrier'));
if ($balikobotSettings = array_filter($balikobotSettings)) {
$fields['Balíkobot dopravce'] = [
'field' => 'balikobot_carrier',
'render' => 'renderBalikobotCarrier',
'spec' => function (QueryBuilder $qb) use ($balikobotSettings) {
$json = json_encode($balikobotSettings);
$qb->addSelect("JSON_VALUE(:json, CONCAT('$.', dt.id_delivery)) as balikobot_carrier")
->leftJoin('o', 'delivery_type', 'dt', 'dt.id=o.id_delivery')
->setParameter('json', $json);
},
'visible' => 'N',
];
}
}
$excludeInherit = ['code', 'date', 'customer', 'price'];
foreach ($tableDef['fields'] as $name => &$field) {
if (!in_array($name, $excludeInherit)) {
$field['visible'] = 'N';
}
$field['translation_section'] = 'orders';
}
$tableDef['fields'] = array_merge(
[
'check' => [
'translate' => true,
'field' => 'id',
'size' => '55px',
'render' => 'renderCheck',
'translation_section' => 'orders',
'type' => '',
'class' => 'hiddenTooltip overflow-visible',
],
],
$tableDef['fields'],
$fields
);
$tableDef = parent::customizeTableDef($tableDef);
return $tableDef;
}
public function getPageDivide(): int
{
$cfg = \KupShop\KupShopBundle\Config::get();
if (!empty($cfg['Modules']['orders_mass_process']['pageDivide'])) {
return $cfg['Modules']['orders_mass_process']['pageDivide'];
}
return parent::getPageDivide();
}
public function getRowClass($values)
{
$class = '';
$action = $this->getAction();
$status = intval(getVal('status', $_POST));
if (!empty($status) && $values['status'] == $status && $action == 'multiInvoiceChangeStatus') {
$class = ' row-green';
}
return $class;
}
public function renderBalikobotCarrier($values, $column)
{
$carrier = $values['balikobot_carrier'];
if (!isset($this->balikobotCarriers)) {
$balikobot = ServiceContainer::getService(Balikobot::class);
$this->balikobotCarriers = $balikobot->getCarriers();
}
return $this->balikobotCarriers[$carrier] ?? '-';
}
public function renderPackages($values, $column)
{
$id_order = $this->getListRowValue($values, 'id');
return HTML::create('input')
->attr('type', 'text')
->attr('style', 'width:60px;')
->attr('name', 'packages['.$id_order.']')
->attr('value', 1);
}
public function renderWeight($values, $column)
{
$id_order = $this->getListRowValue($values, 'id');
global $dbcfg;
if (findModule('products', 'weight')) {
$weight = $this->getOrderWeight($id_order);
}
if (empty($weight)) {
$weight = $dbcfg[$cfg['Modules'][\Modules::BALIKONOS]['provider'] ?? 'balikonos']['weight'] ?? '';
}
return HTML::create('input')
->attr('type', 'text')
->attr('style', 'width:60px;')
->attr('name', 'weights['.$id_order.']')
->attr('value', $weight);
}
public function renderSize($values, $column)
{
$id_order = $this->getListRowValue($values, 'id');
$select = HTML::create('select')
->attr('name', 'sizes['.$id_order.']');
foreach (['Výchozí' => '', 'S' => 'S', 'M' => 'M', 'L' => 'L', 'XL' => 'XL'] as $size => $value) {
$select->tag('option')
->text($size)
->attr('value', $value);
}
return $select;
}
public function renderCustomer($values, $column)
{
$customer = $this->getListRowValue($values, 'customer');
$parts = explode(', ', $customer);
$parts = array_filter($parts);
return join(', ', $parts);
}
public function renderCheck($values, $column)
{
$id_order = $this->getListRowValue($values, 'id');
return [
HTML::create('input')
->attr('type', 'checkbox')
->attr('style', 'margin: 0;')
->attr('checked', 'checked')
->attr('name', 'orders[]')
->attr('value', $id_order),
];
}
public function getOrderWeight($idOrder)
{
return sqlQueryBuilder()->select('total_weight')
->from('orders')->where(Operator::equals(['id' => $idOrder]))
->execute()->fetchOne() ?? 0.0;
}
public function getSQLOrdering(&$var, &$orderParam)
{
parent::getSQLOrdering($var, $orderParam);
if (isset($var['orderField']) && ($var['orderField'] == 'weight' || $var['orderField'] == 'packages')) {
$var['orderField'] = '';
}
if (findModule(Modules::WAREHOUSE) && ($this->getAction() == 'massInvoice' || $this->getAction() == 'edit') && !getVal('order')) {
$var['orderField'] = '('.\KupShop\WarehouseBundle\Query\Orders::orderLocationPositionField('').')';
$var['orderDir'] = 'ASC';
}
}
// TOHLE JE FAKT HNUS, ALE NEZ DELAT PODMINKY NA x SHOPECH, TAK RADSI TADY JEDNOU..
protected function getAction()
{
if (empty($this->action)) {
$acn = getVal('acn');
if (empty($acn)) {
$acn = 'massInvoice';
}
$this->action = $acn;
}
return $this->action;
}
public function getQuery()
{
$qb = parent::getQuery();
$qb->addSelect('CONCAT_WS(", ", o.delivery_name, o.delivery_surname, o.delivery_firm, o.delivery_street, o.delivery_city, o.delivery_zip, o.delivery_country) as customer')
->leftJoin('o', 'order_items', 'oi', 'oi.id_order=o.id')
->groupBy('o.id');
return $qb;
}
public function getFilterQuery(): Query\QueryBuilder
{
$qb = parent::getFilterQuery();
$action = $this->getAction();
if (getVal('balikonos')) {
$qb->andWhere('o.status_storno != 1');
}
if ($action == 'massInvoice') {
if (!getVal('status')) {
if ($qb->getQueryPart('where') == null) {
$qb->andWhere(Operator::inIntArray(getStatuses('active'), 'o.status'));
} else {
$qb->resetQueryPart('where');
if (isset($_REQUEST['orders'])) {
$codes = [];
$codesString = [];
foreach ($_REQUEST['orders'] as $code) {
if (trim($code)) {
$codes[] = intval($code);
$codesString[] = trim($code);
}
}
$qb->andWhere(
Operator::orX(
Operator::inIntArray($codes, 'o.id'),
Operator::inStringArray($codesString, 'o.order_no')
)
);
}
}
}
}
$qb = $this->ordersListFilter->addQueryBuilderParams($qb, $_GET);
if ($action == 'multiInvoiceChangeStatus') {
$qb->resetQueryPart('where');
if (getVal('status')) {
$qb->andWhere(Operator::inIntArray($this->changeOrdersCodes, 'o.id'));
}
}
return $qb;
}
public function handleMultiInvoiceSend()
{
$var = [];
$postType = getVal('postType');
$content = $this->getContent($var, $postType);
if ($postType == 'cp') {
$content = iconv('utf8', 'cp1250//TRANSLIT//IGNORE', $content);
$content = iconv('cp1250', 'utf8', $content);
}
if ($postType == 'ppl') {
$filetype = 'xml';
} elseif ($postType == 'dpd') {
$filetype = 'xlsx';
} else {
$filetype = 'txt';
}
if ($filetype == 'xls' || $filetype == 'xlsx') {
$file = tempnam(sys_get_temp_dir(), 'excel_');
$handle = fopen($file, 'w');
fwrite($handle, $content);
$reader = new Csv();
$reader->setDelimiter(';');
$reader->setInputEncoding('UTF-8');
$spreadsheet = $reader->load($file);
fclose($handle);
unlink($file);
header('Content-Disposition: attachment; filename="'.$postType.'-'.date('Y-m-d_H-i').'.'.$filetype.'"');
if ($filetype == 'xls') {
$writer = new Xls($spreadsheet);
} elseif ($filetype == 'xlsx') {
$writer = new Xlsx($spreadsheet);
}
$writer->save('php://output');
exit;
} else {
header('Content-type: application/'.$filetype);
header('Content-Disposition: attachment; filename="'.$postType.'-'.date('Y-m-d_H-i').'.'.$filetype.'"');
}
echo $content;
exit;
}
/**
* @return bool|mixed|string
*/
protected function getContent($var, $postType)
{
$var['fields'] = ' o.id, order_no, o.delivery_name, o.delivery_surname, o.delivery_firm, o.delivery_type, o.delivery_firm as name,
o.delivery_street, o.delivery_city, o.delivery_zip, o.delivery_country, o.total_price, COUNT(o.id) as amount,
NOW() AS date,o.invoice_phone , o.invoice_email, o.id_delivery,
o.invoice_name, o.invoice_surname, o.invoice_street, o.invoice_city, o.invoice_zip, dtd.name delivery_type_name,
dtd.id as id_dtd, o.note_admin, o.note_user, oh.comment ';
$var['from'] = ' orders AS o
LEFT JOIN delivery_type as dt ON dt.id=o.id_delivery
LEFT JOIN delivery_type_delivery as dtd ON dtd.id=dt.id_delivery
LEFT JOIN orders_history as oh ON oh.id_order=o.id ';
$var['where'] = ' o.id IN (:codes)';
$var['query'] = 'SELECT '.$var['fields'].' FROM '.$var['from'].' WHERE '.$var['where'].' GROUP BY o.id';
$codes = $_REQUEST['orders'];
$indexes = array_flip($codes);
$SQL = sqlQuery($var['query'], ['codes' => $codes], ['codes' => \Doctrine\DBAL\Connection::PARAM_INT_ARRAY]);
$weights = getVal('weights');
$sizes = getVal('sizes');
$packages = getVal('packages');
$orders = [];
foreach ($SQL as $order) {
$order['delivery_suburb'] = '';
if (!empty($order['note_admin'])) {
$order['note_admin'] = json_decode($order['note_admin'], true);
}
if (preg_match('/^(.*) ([0-9\\/]*)$/', trim($order['delivery_street']), $matches)) {
$order['delivery_street'] = trim($matches[1]);
$order['delivery_suburb'] = $matches[2];
}
if (!empty($weights)) {
$order['weight'] = $weights[$order['id']];
}
if (!empty($sizes[$order['id']])) {
$order['size'] = $sizes[$order['id']];
}
if (!empty($packages)) {
$order['packages'] = $packages[$order['id']] ?? 1;
}
$order['note_user'] = $order['note_user'] ?: '';
$order['to_pay'] = roundPrice($order['total_price']);
$orderCls = new Order();
$orderCls->createFromDB($order['id']);
if (findModule('order_payment')) {
$orderCls->total_price = toDecimal($order['total_price']);
$order['to_pay'] = $orderCls->getRemainingPayment();
}
$order['orderclass'] = $orderCls;
$order['delivery_zip'] = strtr($order['delivery_zip'], [' ' => '']);
$orders[$indexes[$order['id']]] = $order;
}
ksort($orders);
global $dbcfg;
preg_match("/\d{3} ?\d{2}/i", $dbcfg['shop_address'], $zip);
/* if ($FileType == "xls"){
return $this->getXLS($orders);
}
*/
$smart = createSmarty(true);
$smart->assign(
[
'orders' => $orders,
'zip' => $zip,
'dbcfg' => $dbcfg,
]
);
$content = $smart->fetch('massprocess/'.$postType.'.tpl');
return $content;
}
public function handleMultiInvoiceChangeStatus()
{
$status = intval(getVal('status'));
if (!is_null($status)) {
foreach (getVal('orders', null, []) as $code) {
$order = new Order();
$order->createFromDB($code);
$email = ServiceContainer::getService(OrderMessageEmail::class);
$order_messages = $email->getOrderStatusMessagesByStatus($status);
if (count($order_messages) == 0) {
$order_message = null;
} else {
$order_message = $order_messages[0]['name'];
}
$this->changeOrdersCodes[] = $code;
$comment = null;
$forceSendMail = null;
if (getVal('donotsend') === 'ON' and $status !== $order->status) {
$order_message = null;
$forceSendMail = false;
$comment = translate('statusChangeComment', 'ordersMassProcess');
}
$order->changeStatus($status, $comment, $forceSendMail, $order_message);
}
}
}
}
return OrdersMassProcessList::class;

View File

@@ -0,0 +1,66 @@
<?php
use KupShop\AdminBundle\AdminList\BaseList;
class OrdersOfSuppliersList extends BaseList
{
protected $tableDef = [
'id' => 'id_supplier',
'fields' => [
'supplier' => ['translate' => true, 'field' => 'name'],
'numOfItems' => ['translate' => true, 'field' => 'pieces'],
'totalPrice' => ['translate' => true, 'field' => 'price', 'render' => 'renderPrice'],
'dateCreated' => ['translate' => true, 'field' => 'date_create'],
],
];
public function getQuery()
{
$priceBuyQuery = $this->getBuyPriceQuery();
$qb = sqlQueryBuilder();
$qb->select('oos.id_supplier, COUNT(*) as count, s.name, SUM(oos.pieces) as pieces, SUM(oos.pieces*COALESCE('.$priceBuyQuery.', pv.price, p.price)) as price, MIN(oos.date_create) as date_create')
->from('orders_of_suppliers', 'oos')
->leftJoin('oos', 'products', 'p', 'p.id = oos.id_product')
->leftJoin('oos', 'products_variations', 'pv', 'pv.id = oos.id_variation')
->leftJoin('oos', 'suppliers', 's', 's.id = oos.id_supplier')
->groupBy('oos.id_supplier');
return $qb;
}
protected function getBuyPriceQuery()
{
$sqlPrice = [];
if (findModule(\Modules::PRODUCTS_SUPPLIERS)) {
$sqlPrice[] = 'SELECT pos.price_buy
FROM products_of_suppliers pos
WHERE pos.id_supplier=oos.id_supplier
AND oos.id_product=pos.id_product
AND ((oos.id_variation IS NULL AND pos.id_variation IS NULL) OR oos.id_variation=pos.id_variation)
AND pos.price_buy > 0';
}
if (findModule(\Modules::PRODUCTS, \Modules::SUB_PRICE_BUY)) {
$sqlPrice[] = 'SELECT COALESCE(pv.price_buy, p.price_buy)
FROM products p
LEFT JOIN products_variations pv ON p.id = pv.id_product
WHERE oos.id_product=p.id
AND ((oos.id_variation IS NULL AND pv.id IS NULL) OR oos.id_variation=pv.id)
AND COALESCE(pv.price_buy, p.price_buy) > 0
LIMIT 1';
}
$sqlPrice[] = 'SELECT sii.price
FROM stock_in_items sii
LEFT JOIN stock_in si ON si.id = sii.id_stock_in
WHERE si.id_supplier=oos.id_supplier AND si.id_index="invoice"
AND oos.id_product=sii.id_product
AND ((oos.id_variation IS NULL AND sii.id_variation IS NULL) OR oos.id_variation=sii.id_variation)
AND sii.price > 0
ORDER BY si.date_issued DESC
LIMIT 1';
return 'COALESCE(('.join('),(', $sqlPrice).'))';
}
}

View File

@@ -0,0 +1,109 @@
<?php
use KupShop\AdminBundle\AdminList\BaseList;
class ParametersList extends BaseList
{
use AdminListSortable;
protected $template = 'listSortable.tpl';
protected $tableName = 'parameters';
protected $showMassEdit = true;
protected $pageDivide = 1000;
protected ?string $tableAlias = 'par';
protected $tableDef = [
'id' => 'id',
'fields' => [
'parameter' => ['translate' => true, 'field' => 'par.name', 'spec' => 'par.name', 'fieldType' => BaseList::TYPE_STRING, 'class' => 'text-bold'],
'name_frontend' => ['translate' => true, 'field' => 'par.name_frontend', 'spec' => 'par.name_frontend', 'fieldType' => BaseList::TYPE_STRING],
'unit' => ['translate' => true, 'field' => 'par.unit', 'spec' => 'par.unit', 'fieldType' => BaseList::TYPE_STRING],
'value_type' => ['translate' => true, 'field' => 'par.value_type', 'spec' => 'par.value_type', 'render' => 'renderType', 'fieldType' => ParametersList::TYPE_LIST],
'uses_count' => ['translate' => true, 'field' => 'cnt'],
'ID' => ['field' => 'id', 'wpjAdmin' => true],
'description' => ['translate' => true, 'field' => 'par.descr', 'spec' => 'par.descr', 'visible' => 'N', 'fieldType' => BaseList::TYPE_STRING],
'figure' => ['translate' => true, 'field' => 'par.figure', 'spec' => 'par.figure', 'visible' => 'N', 'fieldType' => BaseList::TYPE_BOOL],
],
];
public function customizeTableDef($tableDef)
{
$tableDef = parent::customizeTableDef($tableDef);
if (!getVal('name')) {
$tableDef['fields'] = array_merge(
['Pořadí' => ['field' => 'position', 'render' => 'renderPosition', 'class' => 'overflow-visible', 'size' => '70px']],
$tableDef['fields']
);
}
if (findModule(\Modules::PARAMETER_GROUPS)) {
$tableDef['fields']['Skupiny parametrů'] = ['field' => 'parameter_groups', 'visible' => 'N', 'spec' => function (Query\QueryBuilder $qb) {
$qbParameterGroups = sqlQueryBuilder()
->select('GROUP_CONCAT(DISTINCT pg.name SEPARATOR ", ")')
->from('parameter_groups', 'pg')
->innerJoin('pg', 'parameter_groups_items', 'pgi', 'pg.id=pgi.id_parameter_group')
->innerJoin('pgi', 'parameter_groups_items_parameters', 'pgip', 'pgi.id=pgip.id_parameter_group_item')
->where('pgip.id_parameter = par.id');
$qb->addSubselect($qbParameterGroups, 'parameter_groups');
}];
}
$tableDef['fields']['value_type']['fieldOptions'] = [
'int' => translate('int', 'parameters'),
'char' => translate('char', 'parameters'),
'list' => translate('list', 'parameters'),
];
return $tableDef;
}
public function renderType($values, $column)
{
$value = $this->getListRowValue($values, $column['field']);
switch ($value) {
case 'float':
$value = 'číslo';
break;
case 'char':
$value = 'text';
break;
case 'list':
$value = 'seznam';
break;
}
return "{$value}";
}
public function handle()
{
parent::handle();
$item = getVal('moved_item');
if (!empty($item)) {
$this->saveList($item, 'parameters');
exit('{}');
}
}
public function getQuery()
{
$qb = sqlQueryBuilder()
->select('par.*', 'COUNT(pp.id) as cnt')
->from('parameters', 'par')
->leftJoin('par', 'parameters_products', 'pp', 'pp.id_parameter = par.id')
->groupBy('par.id');
extract($_GET, EXTR_SKIP | EXTR_REFS);
if (isset($name) && $name) {
$qb->where('name LIKE :name')->setParameter('name', '%'.$name.'%');
}
return $qb;
}
}

201
admin/lists/PhotosList.php Normal file
View File

@@ -0,0 +1,201 @@
<?php
use KupShop\AdminBundle\AdminList\BaseList;
use KupShop\KupShopBundle\Query\JsonOperator;
use Query\Operator;
class PhotosList extends BaseList
{
protected $template = 'list/photos.tpl';
protected $pageDivide = 150;
protected $orderParam = [
'sort' => 'Datum',
'direction' => 'DESC',
];
protected $tableDef = [
'id' => 'id',
'fields' => [
'Obrázek' => ['field' => 'id'],
'Název' => ['field' => 'descr'],
'Datum' => ['field' => 'date'],
],
];
public function getSQL(Query\QueryBuilder $qb)
{
global $cfg;
$data = parent::getSQL($qb);
$links = [];
foreach ($data['SQL'] as $key => $row) {
$links[$key] = $row;
$links[$key]['img'] = getImage($row['id'], $row['image_2'], $row['source'], 4, $row['descr'], strtotime($row['date_update']));
}
$data['SQL'] = $links;
return $data;
}
public function getPageDivide()
{
if (getVal('searchWnd')) {
return parent::getPageDivide() - 1;
}
return parent::getPageDivide();
}
public function handleUploadImage()
{
$success = 'false';
$photoId = null;
$image = getVal('uploader', $_FILES);
$filename = getVal('qqfilename');
if (!empty($image)) {
$photoId = $this->uploadImage($image, $filename);
if ($photoId) {
$success = 'true';
}
}
header('Content-Type: application/json');
echo json_encode([
'success' => $success,
'id' => $photoId,
]);
exit;
}
protected function uploadImage($image, $filename)
{
$img = new Photos('none');
$img->newImage($this->getID());
// uploadovat obrazek
$img->uploadPhotoOrVideo($image, $filename);
return $img->getID();
}
public function getQuery()
{
$qb = sqlQueryBuilder()
->select('p.*')
->from('photos', 'p')
->groupBy('p.id');
if (findModule(Modules::VIDEOS)) {
$qb->addSelect('v.id_cdn id_video')
->leftJoin('p', 'videos', 'v', 'p.id = v.id_photo');
}
extract($_GET, EXTR_SKIP | EXTR_REFS);
if ($photosType = getVal('photos_type')) {
$objectIdField = null;
switch ($photosType) {
case 'products':
$objectIdField = 'ppr.id_product';
$qb->join('p', 'photos_products_relation', 'ppr', 'p.id = ppr.id_photo');
break;
case 'pages':
$objectIdField = null;
$qb->leftJoin('p', 'photos_menu_relation', 'ppr', 'p.id = ppr.id_photo')
->leftJoin('p', 'photos_blocks_new_relation', 'pbnr', 'p.id = pbnr.id_photo');
if ($objectId = getVal('id_object')) {
$spec = Operator::orX(
Operator::equals(['ppr.id_menu' => $objectId]),
'pbnr.id_block IN (b.id)'
);
$qb->leftJoin('p', 'menu_links', 'ml', 'ml.id = :page_object_id')
->leftJoin('ml', 'blocks', 'b', 'b.id_root = ml.id_block')
->andWhere($spec)
->setParameter('page_object_id', $objectId);
}
break;
case 'articles':
$objectIdField = 'ppr.id_art';
$qb->join('p', 'photos_articles_relation', 'ppr', 'p.id = ppr.id_photo');
break;
case 'producers':
$objectIdField = 'ppr.id_producer';
$qb->join('p', 'photos_producers_relation', 'ppr', 'p.id = ppr.id_photo');
break;
case 'no':
$qb->leftJoin('p', 'photos_products_relation', 'ppr', 'p.id = ppr.id_photo')
->leftJoin('p', 'photos_producers_relation', 'pprr', 'p.id = pprr.id_photo')
->leftJoin('p', 'photos_articles_relation', 'par', 'p.id = par.id_photo')
->leftJoin('p', 'photos_menu_relation', 'pmr', 'p.id = pmr.id_photo')
->andWhere('ppr.id_photo IS NULL AND pprr.id_photo IS NULL AND par.id_photo IS NULL AND pmr.id_photo IS NULL');
break;
case 'videos':
$objectIdField = 'p.id';
$qb->andWhere('v.id_photo is not null');
break;
case 'photos':
$objectIdField = 'p.id';
if (findModule(Modules::VIDEOS)) {
$qb->andWhere('v.id_photo is null');
}
break;
}
if (($objectId = getVal('id_object')) && $objectIdField) {
$qb->andWhere(\Query\Operator::equals([$objectIdField => $objectId]));
}
}
if ($filename = getVal('filename')) {
$qb->andWhere('p.filename LIKE :filename')
->setParameter('filename', '%'.$filename.'%');
}
if ($descr = getVal('descr')) {
$qb->andWhere('p.descr LIKE :descr')
->setParameter('descr', '%'.$descr.'%');
}
// ###########
if (!empty($_GET['IDp'])) {
$qb->from('photos_products_relation', 'pp')->andWhere('p.id=pp.id_photo')->andWhere('pp.id_product=:IDp')
->setParameter('IDp', $_GET['IDp']);
}
// ###########
if (!empty($_GET['IDa'])) {
$qb->from('photos_articles_relation', 'pa')->andWhere('p.id=pa.id_photo AND pa.id_art=":IDa" ')
->setParameter('IDa', $_GET['IDa']);
}
// ###########
if (!empty($_GET['name'])) {
$qb->andWhere('p.descr LIKE "%'.$_GET['name'].'%" ');
}
// ###########
if (!empty($_GET['ID'])) {
$qb->andWhere(Operator::equals(['p.id' => intval($_GET['ID'])]));
}
// ###########
if (!empty($_GET['year'])) {
if ($_GET['year'] == 'null') {
$qb->andWhere('p.date=0');
} else {
$qb->andWhere('YEAR(p.date)=:year')->setParameter('year', $_GET['year']);
}
}
// ###########
if (!empty($_GET['month'])) {
$qb->andWhere('MONTH(p.date)=:month')->setParameter('month', $_GET['month']);
}
// ###########
if (!empty($_GET['check'])) {
$qb->andWhere(JsonOperator::exists('p.data', 'invalid'));
}
return $qb;
}
}

96
admin/lists/PosList.php Normal file
View File

@@ -0,0 +1,96 @@
<?php
use KupShop\AdminBundle\AdminList\BaseList;
class PosList extends BaseList
{
protected $template = 'list/pos.tpl';
public function __construct()
{
if (getVal('pagedivide') != '') {
$this->pageDivide = getVal('pagedivide');
}
}
protected $tableDef = [
'id' => 'id',
'fields' => [
'ID' => ['field' => 'pos.id', 'size' => 1],
'Datum' => ['field' => 'date', 'size' => 2.2, 'render' => 'renderTimestamp'],
'Objednávka' => ['field' => 'id_order', 'size' => 1, 'type' => 'order', 'type_id' => 'id_order'],
'Přijato' => ['field' => 'price', 'render' => 'renderShowInserted', 'size' => 1.3],
'Vydáno' => ['field' => 'price', 'render' => 'renderShowChoosed', 'size' => 1.3],
'Typ platby' => ['field' => 'method', 'render' => 'renderPayMethod', 'size' => 1],
'Popis' => ['field' => 'note', 'size' => 3],
'Zpracoval' => ['field' => 'admin', 'size' => 1],
],
'class' => 'getRowClass',
];
public function renderShowInserted($values, $column)
{
$price = $this->getListRowValue($values, $column['field']);
if ($price > 0) {
return $this->renderPrice($values, $column);
}
}
public function renderShowChoosed($values, $column)
{
$price = $this->getListRowValue($values, $column['field']);
if ($price < 0) {
$values['price'] = $price * -1;
return $this->renderPrice($values, $column);
}
}
public function renderTimestamp($values, $column)
{
$timestamp = $this->getListRowValue($values, $column['field']);
$days = ['Pondělí', 'Úterý', 'Středa', 'Čtvrtek', 'Pátek', 'Sobota', 'Neděle'];
return $days[date('N', $timestamp) - 1].' '.date('j.n.Y H:i:s', $timestamp);
}
public function getRowClass($values)
{
return ($values['price'] > 0) ? 'row-green' : 'row-red';
}
public function renderPayMethod($values, $column)
{
$method = $this->getListRowValue($values, $column['field']);
switch ($method) {
case '1':
return 'Hotově';
case '2':
return 'Kartou';
case '3':
return 'Na fakturu';
default:
return '';
}
}
public function getQuery()
{
$qb = sqlQueryBuilder()
->select('pos.id', 'pos.note', 'pos.price', 'a.login as admin', 'pos.method', 'pos.id_order', 'UNIX_TIMESTAMP(date) AS date')
->from('order_payments', 'pos')
->leftJoin('pos', 'admins', 'a', 'pos.admin=a.id');
$method = getVal('method');
if (!empty($method)) {
$qb->where('pos.method = ?')->setParameter(0, $method);
}
$qb2 = sqlQueryBuilder()->select('SUM(price) as in_pos')->from('order_payments')->where('method=1 OR method=4 OR method=5');
$SQL = $qb2->execute();
$var['in_pos'] = sqlFetchArray($SQL)['in_pos'];
return ['qb' => $qb, 'in_pos' => $var['in_pos']];
}
}

View File

@@ -0,0 +1,51 @@
<?php
use KupShop\AdminBundle\AdminList\BaseList;
class PricelevelsList extends BaseList
{
protected $tableName = 'price_levels';
protected ?string $tableAlias = 'pl';
protected $tableDef = [
'id' => 'pl.id',
'fields' => [
'Cenová hladina' => ['field' => 'pl.name'],
'Sleva' => ['field' => 'pl.discount', 'render' => 'renderDiscount'],
'Popis' => ['field' => 'pl.descr'],
],
];
public function renderDiscount($values, $column)
{
global $dbcfg;
$value = $this->getListRowValue($values, $column['field']);
if (isset($values['unit'])) {
switch ($values['unit']) {
case 'perc':
return "{$value}%";
case 'price':
return "{$value} ".$dbcfg->currency;
}
}
return "{$value}";
}
public function getFilterQuery(): \Query\QueryBuilder
{
$qb = parent::getFilterQuery();
if ($name = getVal('name')) {
$qb->andWhere(\KupShop\CatalogBundle\Query\Search::searchFields(
$name,
[
['field' => 'name', 'match' => 'both'],
['field' => 'descr', 'match' => 'both'],
]
));
}
return $qb;
}
}

View File

@@ -0,0 +1,531 @@
<?php
namespace Admin\Lists;
use KupShop\AdminBundle\AdminList\BaseList;
use KupShop\AdminBundle\AdminList\FiltersStorage;
use KupShop\AdminBundle\Util\ProductListFilter;
use KupShop\CatalogBundle\Query\Search;
use KupShop\KupShopBundle\Config;
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
use KupShop\KupShopBundle\Util\HtmlBuilder\HTML;
use Query\Operator;
use Query\QueryBuilder;
class ProductsList extends BaseList
{
use \AdminListSortable;
use FiltersStorage;
protected $template = 'list/products.tpl';
protected $showMassEdit = true;
protected $tableName = 'products';
protected ?string $tableAlias = 'p';
protected $tableDef = [
'id' => 'p.id',
'fields' => [
'photo' => ['field' => 'p.title', 'size' => '80px', 'render' => 'renderImage', 'visible' => 'N', 'translate' => true],
'title' => ['translate' => true, 'field' => 'p.title', 'size' => 4, 'type' => 'products', 'spec' => 'p.title', 'fieldType' => BaseList::TYPE_STRING],
'productNumber' => ['translate' => true, 'field' => 'p.id'],
'code' => ['translate' => true, 'field' => 'p.code'],
'campaign' => ['translate' => true, 'field' => 'p.campaign', 'spec' => 'p.campaign', 'render' => 'renderCampaign', 'class' => 'columnCampaigns product-campaigns', 'fieldType' => BaseList::TYPE_LIST_MULTISELECT],
'price' => ['translate' => true, 'field' => 'p.price', 'spec' => 'p.price', 'render' => 'renderPricePreferred', 'class' => 'alignRight text-right', 'label' => 'labelPricePreferred', 'vat' => 'Y', 'fieldType' => BaseList::TYPE_PRICE],
'priceWithDiscount' => ['translate' => true, 'field' => 'priceWithDiscount', 'spec' => '(p.price - ((p.price * p.discount) / 100)) as priceWithDiscount', 'render' => 'renderPricePreferred', 'class' => 'alignRight text-right', 'label' => 'labelPricePreferredWithDiscount', 'vat' => 'Y', 'visible' => 'N'],
'priceWithoutVat' => ['translate' => true, 'field' => 'p.price', 'spec' => 'p.price', 'render' => 'renderPrice', 'class' => 'alignRight text-right', 'visible' => 'N', 'vat' => 'N', 'fieldType' => BaseList::TYPE_PRICE],
'Datum přidání' => ['field' => 'p.date_added', 'render' => 'renderDate'],
'Skladem ks' => ['field' => 'p.in_store', 'spec' => 'p.in_store', 'visible' => 'N', 'render' => 'renderFloat'],
'Varianty' => ['field' => 'variations', 'spec' => "GROUP_CONCAT(DISTINCT CONCAT(pv.title, ' - ', TRIM(pv.in_store)+0, ' ks') ORDER BY pv.id ASC) as variations", 'render' => 'renderVariations', 'export' => 'exportVariations', 'class' => 'text-wrap tiny-list-items', 'visible' => 'N'],
'Pozice' => ['field' => 'p.position', 'spec' => 'p.position', 'visible' => 'N', 'render' => 'renderProductPosition'],
'Ean' => ['field' => 'p.ean', 'visible' => 'N'],
'shortDescription' => ['translate' => true, 'field' => 'p.short_descr', 'spec' => 'p.short_descr', 'visible' => 'N', 'fieldType' => BaseList::TYPE_STRING],
'longDescription' => ['translate' => true, 'field' => 'p.long_descr', 'spec' => 'p.long_descr', 'visible' => 'N', 'fieldType' => BaseList::TYPE_STRING],
],
'class' => 'getRowClass',
];
public function getRowClass($values)
{
$class = '';
if ($values['figure'] == 'O') {
$class .= ' info';
} elseif ($values['figure'] != 'Y') {
$class .= ' danger';
}
if ($this->isImageVisible()) {
$class .= ' product-list-thumbnail';
}
return $class;
}
public function renderProductPosition($values)
{
return match ($values['position']) {
POSITION_FIRST => 'Vpředu',
POSITION_LAST => 'Vzadu',
null => 'Standartní řazení',
default => $values['position'],
};
}
public function renderVariations($values, $column)
{
$variations = $this->getListRowValue($values, $column['field']);
$variations = explode(',', $variations ?: '');
$ret = [];
foreach ($variations as $variation) {
$ret[] = HTML::create('span')
->tag('p')
->text($variation)
->end();
}
return $ret;
}
public function exportVariations($values, $column)
{
$array = explode(',', $this->getListRowValue($values, $column['field']));
return $this->exportArray($array);
}
public function renderCampaign($values, $column)
{
$label = $this->getListRowValue($values, $column['field']);
if (empty($label)) {
return '';
}
global $cfg;
$flags = preg_split('/,/', $label);
$campaign_colors = ['N' => ' badge-pastel-primary',
'A' => ' badge-pastel-danger',
'V' => ' badge-pastel-warning',
'S' => 'badge-pastel-default',
'L' => 'badge-pastel-default',
'M' => 'badge-pastel-default',
'Z' => 'badge-pastel-default',
];
$ret = [];
foreach (array_intersect($flags, array_keys($cfg['Products']['Flags'])) as $flag) {
$hidden = $cfg['Products']['Flags'][$flag]['hidden'] ?? false;
if (!$hidden) {
$short = $cfg['Products']['Flags'][$flag]['short'];
$title = $cfg['Products']['Flags'][$flag]['singular'] != '' ? $cfg['Products']['Flags'][$flag]['singular'] : $short;
$class = getVal($flag, $campaign_colors);
$ret[] = HTML::create('span')
->class('badge '.$class)
->tag('span')->class('tooltip-text')->text($title)->end()
->tag('span')->class('badge-text')->text($short)->end();
}
}
return $ret;
}
public function renderLabels($values, $column)
{
$labels = $this->getListRowValue($values, 'label_values');
if (empty($labels)) {
return [];
}
$labels = json_decode($labels, true);
$ret = [];
foreach ($labels as $label) {
$ret[] = HTML::create('span')
->class('badge')
->tag('span')->class('tooltip-text')->text($label['name'])->end()
->tag('span')->class('badge-text')->text($label['short_name'] ?: $label['name'])->end();
}
return $ret;
}
public function renderImage($values, $column)
{
$id = $this->getListRowValue($values, 'id');
$SQL = sqlQueryBuilder()->select('ph.id', 'ph.source', 'ph.image_2', 'php.show_in_lead')
->from('photos', 'ph')
->leftJoin('ph', 'photos_products_relation', 'php', 'ph.id=php.id_photo')
->where(Operator::equals(['php.id_product' => $id, 'php.show_in_lead' => 'Y']))
->execute();
foreach ($SQL as $row) {
$img = getImage($row['id'], $row['image_2'], $row['source'], 4);
}
global $cfg;
$ret = [];
if (empty($img)) {
$ret[] = \KupShop\KupShopBundle\Util\HtmlBuilder\HTML::create('img')
->class('img img-rounded')
->attr('src', '/admin/static/images/no-image.png');
} else {
$ret[] = \KupShop\KupShopBundle\Util\HtmlBuilder\HTML::create('img')
->class('img img-rounded')
->attr('src', $this->getUrlFinder()->staticUrl($img['source']));
}
return $ret;
}
public function labelPricePreferredWithDiscount(): string
{
switch (\Settings::getDefault()->prod_prefer_price_vat) {
case 'Y':
return 'Prodejní cena s DPH';
case 'F':
return 'Prodejní cena finální';
default:
case 'N':
return 'Prodejní cena bez DPH';
}
}
public function customizeTableDef($tableDef)
{
$tableDef = parent::customizeTableDef($tableDef);
if (findModule(\Modules::POHODA)) {
$tableDef['fields']['Datum posl. synch.'] = ['field' => 'p.pohoda_sync_date', 'render' => 'renderDateTime', 'visible' => 'Y'];
}
if (findModule(\Modules::PRODUCTS, \Modules::SUB_NOTE)) {
$tableDef['fields']['Poznámka'] = [
'field' => 'p.note',
'spec' => 'COALESCE(GROUP_CONCAT(DISTINCT NULLIF(pv.note, "")), p.note) as note',
'visible' => 'N',
];
}
$tableDef['fields']['Výrobce'] = [
'field' => 'producer_name',
'spec' => function (QueryBuilder $qb) {
$qb->addSelect('pr.name as producer_name')
->leftJoin('p', 'producers', 'pr', 'p.producer = pr.id');
},
'visible' => 'N',
];
if (findModule(\Modules::WAREHOUSE)) {
$tableDef['fields']['Pozice ve skladu'] = [
'field' => 'warehouse_position',
'size' => 2,
'spec' => function (QueryBuilder $qb) {
$qb->addSelect('GROUP_CONCAT(DISTINCT wp.code SEPARATOR ", ") as warehouse_position')
->leftJoin('p', 'warehouse_products', 'wpr', 'p.id = wpr.id_product AND (pv.id = wpr.id_variation OR wpr.id_variation is null)')
->leftJoin('wpr', 'warehouse_positions', 'wp', 'wpr.id_position = wp.id');
},
];
}
if (findModule(\Modules::STOCK_IN)) {
$tableDef['fields']['stockInDate'] = [
'field' => 'p.date_stock_in',
'spec' => 'p.date_stock_in',
'render' => 'renderDate',
'visible' => 'N',
'translate' => true,
];
}
if (findModule(\Modules::LABELS, \Modules::SUB_PRODUCT_LABELS)) {
$tableDef['fields']['labels'] = [
'field' => 'label_values',
'render' => 'renderLabels',
'class' => 'columnCampaigns',
'translate' => true,
'fieldType' => BaseList::TYPE_LIST_MULTISELECT_AUTOCOMPLETE,
'fieldOptions' => ['autocomplete' => 'labels', 'table' => 'labels', 'fieldType' => 'json', 'prefetchField' => 'short_name'],
'spec' => function (QueryBuilder $qb) {
$qb->addSubselect(
sqlQueryBuilder()
->select('JSON_OBJECTAGG(l.id, JSON_OBJECT("short_name", l.short_name, "name", l.name, "id", l.id))')
->from('product_labels_relation', 'plr')
->leftJoin('plr', 'labels', 'l', 'plr.id_label = l.id')
->andWhere('plr.id_product = p.id'), 'label_values'
);
},
];
}
if (findModule(\Modules::PRODUCTS, \Modules::SUB_UNITS)) {
$tableDef['fields']['measure_unit'] = [
'field' => 'measure_unit',
'spec' => function (QueryBuilder $qb) {
$qb->addSelect('COALESCE(pu2.short_name_admin, pu2.short_name) unit_name, p.measure_unit')
->leftJoin('p', 'products_units', 'pu2', 'p.measure_unit = pu2.id');
},
'translate' => true,
'visible' => 'Y',
'render' => 'renderMeasureUnit',
'fieldType' => BaseList::TYPE_LIST_AUTOCOMPLETE,
'fieldOptions' => [
'autocomplete' => 'units',
'prefetchField' => 'unit_name',
],
];
$tableDef['fields']['measure_quantity'] = [
'field' => 'p.measure_quantity',
'spec' => 'p.measure_quantity',
'visible' => 'Y',
'translate' => true,
'fieldType' => BaseList::TYPE_FLOAT,
];
}
global $cfg;
foreach ($cfg['Products']['Flags'] as $flag => $value) {
$tableDef['fields']['campaign']['fieldOptions'][$flag] = $value['singular'];
}
return $tableDef;
}
protected function isImageVisible()
{
return $this->getTableDef()['fields']['photo']['visible'] == 'Y';
}
public function getQuery()
{
$cfg = Config::get();
$dbcfg = \Settings::getDefault();
$qb = sqlQueryBuilder()
->select('p.id', 'p.code', 'p.figure', 'p.date_added', 'p.discount', 'p.vat', 'p.ean')
->from('products', 'p')
->leftJoin('p', 'products_variations', 'pv', 'p.id=pv.id_product')
->where('p.id != 0')
->groupBy('p.id');
$var['showImages'] = $this->isImageVisible();
$var['url'] = $_SERVER['REQUEST_URI'];
$filter = getVal('filter', null, []);
if (!empty($filter)) {
// extended search
ServiceContainer::getService(ProductListFilter::class)->applyFilter($filter, $qb);
return [
'qb' => $qb,
'showImages' => $var['showImages'],
'url' => $_SERVER['REQUEST_URI'],
];
}
extract($_GET, EXTR_SKIP | EXTR_REFS);
$IDsec = getVal('IDsec');
$comments = getVal('comments');
$adminID = getVal('adminID');
if (!empty($_GET['IDsec']) && empty($campaign)) {
$qb->leftJoin('p', 'products_in_sections', 'ps', 'p.id=ps.id_product')
->andWhere('ps.id_section=:id_section')
->setParameter('id_section', $_GET['IDsec']);
}
// ###########
if (isset($_GET['nosec'])) {
$qb->resetQueryPart('from');
$qb->from('products', 'p')
->leftJoin('p', 'products_in_sections', 'ps', 'p.id = ps.id_product')
->andWhere('ps.id_product IS NULL');
}
// ###########
if (isset($_GET['noimage'])) {
$qb->resetQueryPart('from');
$qb->from('products', 'p')
->leftJoin('p', 'photos_products_relation', 'ppr', 'p.id = ppr.id_product AND ppr.show_in_lead="Y"')
->andWhere('ppr.id_product IS NULL');
}
if (isset($_GET['in_store'])) {
$qb->andWhere('p.in_store > 0');
}
// ###########
if (!empty($IDp)) {
$IDp = trim($IDp);
$qb->andWhere('p.id=:pid')
->setParameter('pid', $IDp);
}
// ###########
if (!empty($IDvv)) {
$IDvv = trim($IDvv);
$qb->join('pv', 'products_variations_combination', 'pvcv', 'pv.id=pvcv.id_variation')
->andWhere('pvcv.id_value=:idvv')
->setParameter('idvv', $IDvv);
}
// ###########
if (!empty($idCode)) {
$searchFields = $this->getCodeSearchFields($qb);
if (!empty($cfg['Modules']['products_variations']['variationCode'])) {
$searchFields = array_merge($searchFields, [['field' => 'pv.code', 'match' => 'both', 'order' => '1']]);
}
if (findModule(\Modules::PRODUCTS_SUPPLIERS)) {
$qb->leftJoin('p', 'products_of_suppliers', 'pofs', 'p.id = pofs.id_product');
$searchFields = array_merge($searchFields, [['field' => 'pofs.code', 'match' => 'both', 'order' => '1']]);
}
$qb->andWhere(Search::searchFields($idCode, $searchFields));
}
// ###########
if (!empty($code)) {
$code = trim($code);
$qb->andWhere('p.code LIKE :code')
->setParameter('code', '%'.$code.'%');
if (!empty($cfg['Modules']['products_variations']['variationCode'])) {
$qb->orWhere('pv.code LIKE :code');
}
if (findModule(\Modules::PRODUCTS_SUPPLIERS)) {
$qb->leftJoin('p', 'products_of_suppliers', 'pofs', 'p.id = pofs.id_product')
->orWhere('pofs.code LIKE :pofs_code')
->setParameter('pofs_code', $code);
}
}
// ###########
if (!empty($title)) {
$this->addFilterForTitle($title, $qb);
}
if (!empty($ean)) {
$ean = trim($ean);
$qb->andWhere('p.ean LIKE :ean OR pv.ean LIKE :ean')
->setParameter('ean', '%'.intval($ean).'%');
}
// ###########
$IDpr = getVal('IDpr');
if (!empty($IDpr)) {
$IDpr = trim($IDpr);
$qb->andWhere('p.producer=:id_producer')
->setParameter('id_producer', $IDpr);
}
// ###########
if (!empty($campaign)) {
$qb->andWhere('FIND_IN_SET(:campaign, p.campaign)>0')
->setParameter('campaign', $campaign);
if (!empty($_GET['IDsec'])) {
$qb->join('p', 'products_in_sections', 'ps',
'p.id=ps.id_product AND FIND_IN_SET(:campaign2, p.campaign)>0 AND ps.id_section=:ps_id_section'
)
->setParameter('campaign2', $campaign)
->setParameter('ps_id_section', $_GET['IDsec']);
}
}
// ###########
if (!empty($figure)) {
$qb->andWhere('p.figure=:figure')
->setParameter('figure', $figure);
}
// ###########
// zobrazeni zbozi s novymu komentari
if ($comments == 'new' && $adminID > 0) {
$qb2 = sqlQueryBuilder()
->select('date_access')
->from('admins_accesses')
->where('id_admin=:id_admin AND login_status="OK"')
->setParameter('id_admin', intval($adminID))
->orderBy('id', 'DESC')
->setMaxResults(1)
->setFirstResult(1);
$dateLogin = $qb2->execute()->fetch()['date_access'];
if (empty($dateLogin)) {
$dateLogin = date('Y-m-d').' 00:00:00';
}
$qb->join('p', 'comments', 'c')
->where('c.type="product" AND c.id_item=p.id AND c.date >= :comment_date')
->setParameter('comment_date', $dateLogin);
}
// ###########
if (!empty($show_in_feed)) {
$qb->andWhere('p.show_in_feed=:show_in_feed')
->setParameter('show_in_feed', $show_in_feed);
}
// ###########
if (!empty($parameter_value)) {
$qb->leftJoin('p', 'parameters_products', 'pp', 'pp.id_product = p.id')
->andWhere('pp.value_list=:id_pp_value')
->setParameter('id_pp_value', $parameter_value);
}
if (!empty($template_id)) {
$qb->leftJoin('p', 'templates_products', 'tp', 'tp.id_product = p.id')
->andWhere(\Query\Operator::equals(['tp.id_template' => $template_id]));
}
// ###########
if (!getVal('showOld')) {
$qb->andWhere('p.figure != "O" ');
}
if (($parameterID = getVal('parameterId')) && ($parameterValue = getVal('parameterValue'))) {
$qb->leftJoin('p', 'parameters_products', 'pp', 'pp.id_parameter = :id_parameter AND pp.id_product = p.id')
->leftJoin('pp', 'parameters_list', 'pl', 'pl.id = pp.value_list')
->andWhere('(pp.value_char LIKE :parameter_value) OR (pp.value_float LIKE :parameter_value) OR (pl.value LIKE :parameter_value)')
->addParameters(['id_parameter' => $parameterID, 'parameter_value' => $parameterValue.'%']);
}
if (findModule(\Modules::POHODA)) {
$qb->addSelect('p.pohoda_sync_date');
}
return [
'qb' => $qb,
'showImages' => $var['showImages'],
'url' => $_SERVER['REQUEST_URI'],
];
}
protected function getCodeSearchFields(QueryBuilder $qb): array
{
return [
['field' => 'p.code', 'match' => 'both', 'order' => '1'],
['field' => 'p.id', 'match' => 'both', 'order' => '1'],
];
}
protected function addFilterForTitle($title, $qb): void
{
$search = get_search_query($title, [['field' => 'p.title', 'match' => 'both']]);
$qb->andWhere($search['where']);
foreach ($search['data'] as $title => $data) {
$qb->setParameter($title, $data);
}
}
public function renderMeasureUnit($values, $column)
{
return $values['unit_name'] ?? '';
}
}
return ProductsList::class;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,124 @@
<?php
use KupShop\AdminBundle\AdminList\BaseList;
use KupShop\AdminBundle\AdminList\FiltersStorage;
use KupShop\AdminBundle\Query\Invert;
class ProductsOfSuppliersList extends BaseList
{
use FiltersStorage;
protected $showMassEdit = true;
protected $tableName = 'products_of_suppliers';
protected ?string $tableAlias = 'pos';
protected $tableDef = [
'id' => 'pos.id',
'fields' => [
'ID' => ['field' => 'pos.id', 'size' => 0.5],
'product' => ['translate' => true, 'field' => 'p.title', 'spec' => 'p.title', 'size' => 2, 'type' => 'product', 'type_id' => 'p_id', 'fieldType' => BaseList::TYPE_STRING],
'variation' => ['translate' => true, 'field' => 'pv_title', 'size' => 1],
'supplier' => ['translate' => true, 'field' => 's.name'],
'code' => ['translate' => true, 'field' => 'pos.code'],
'supplierEAN' => ['translate' => true, 'field' => 'pos.ean', 'visible' => 'N'],
'ean' => ['translate' => true, 'field' => 'product_ean', 'visible' => 'N'],
'inStore' => ['translate' => true, 'field' => 'pos.in_store', 'spec' => 'pos.in_store', 'size' => 0.5, 'fieldType' => BaseList::TYPE_INT],
// 'VOC Dod.' => ['field'=>'pos.price_buy', 'size'=>0.5, 'class'=>'right', 'render'=>function ($label, $variables]{return $label > 0 ? setPrice($variables['price_buy'], null, $variables['vat']] : "-";}],
'lastSync' => ['translate' => true, 'field' => 'pos.last_sync', 'size' => 1, 'visible' => 'N'], // 'class'=>'center'
'productCode' => ['translate' => true, 'field' => 'product_code', 'visible' => 'N'],
'figure' => ['field' => 'figure', 'translate' => true, 'translation_section' => 'products', 'visible' => 'N', 'render' => 'renderFigure'],
'priceBuy' => ['field' => 'pos.price_buy', 'translate' => true, 'visible' => 'N', 'spec' => 'pos.price_buy', 'fieldType' => BaseList::TYPE_PRICE],
'priceSell' => ['field' => 'pos.price_sell', 'translate' => true, 'visible' => 'N', 'spec' => 'pos.price_sell', 'fieldType' => BaseList::TYPE_PRICE],
'note' => ['translate' => true, 'field' => 'pos.note', 'spec' => 'pos.note', 'visible' => 'N', 'fieldType' => BaseList::TYPE_STRING],
],
'class' => 'getRowClass',
];
protected $showAddItem = 'data[id_product]={productId}&data[id_variation]={variationId}';
protected $figure;
public function getRowClass($values)
{
$dbcfg = Settings::getDefault();
$class = '';
if ($dbcfg->highlight_order_rows == 'Y') {
if ($values['figure'] == 'O') {
$class .= ' info';
} elseif ($values['figure'] != 'Y') {
$class .= ' danger';
}
}
return $class;
}
public function renderFigure($values, $column)
{
$value = $this->renderCell($values, $column);
if (!isset($this->figure)) {
$this->figure = [
'Y' => translate('figureVisible', 'products'),
'N' => translate('figureHidden', 'products'),
'O' => translate('figureSaleEnd', 'products'),
];
}
return $this->figure[$value] ?? '';
}
public function getQuery()
{
/** @var \KupShop\ElninoBundle\Query\QueryBuilder $qb */
$qb = sqlQueryBuilder()
->select('pos.id', 'pos.id ID', 'p.figure as figure', 'pv.title pv_title', 's.name', 'pos.code', 'pos.ean',
'DATE_FORMAT(pos.last_sync, "'.$GLOBALS['dbcfg']['date_format'].' '.$GLOBALS['dbcfg']['time_format'].'") as last_sync',
'p.id as p_id', 'v.vat', 'COALESCE(p.code) AS product_code', 'p.ean product_ean')
->from('products_of_suppliers', 'pos')
->leftJoin('pos', 'suppliers', 's', 'pos.id_supplier=s.id')
->leftJoin('pos', 'products', 'p', 'pos.id_product=p.id')
->leftJoin('pos', 'products_variations', 'pv', 'pos.id_variation=pv.id')
->leftJoin('p', 'vats', 'v', 'v.id=p.vat')
->where(1);
extract($_REQUEST, EXTR_SKIP | EXTR_REFS);
// ###########
if (!empty($IDs)) {
$qb->andWhere('(pos.id=:idsParam1 OR pos.code LIKE :idsParam2)')
->setParameter('idsParam1', "{$IDs}")
->setParameter('idsParam2', "%{$IDs}");
}
if (!empty($EAN)) {
$qb->andWhere(\Query\Operator::like(['pos.ean' => "%{$EAN}%"]));
}
// ###########
if (!empty($supplier)) {
$qb->andWhere(\Query\Operator::equals(['pos.id_supplier' => $supplier]));
unset($fields, $name);
}
// ###########
if (!empty($producer)) {
$qb->andWhere(\Query\Operator::equals(['p.producer' => $producer]));
unset($fields, $name);
}
// ###########
if (!empty($productId)) {
$variationId = getVal('variationId');
$qb->andWhere(\Query\Operator::equals(['pos.id_product' => $productId]));
if ($variationId > 0) {
$qb->andWhere(\Query\Operator::equals(['pos.id_variation' => intval($variationId)]));
}
} elseif (!empty($productId_text)) {
$qb->andWhere('p.title LIKE :p_title_like')->setParameter('p_title_like', '%'.$productId_text.'%');
}
if (!empty($figure)) {
$qb->andWhere(Invert::checkInvert(\Query\Operator::inStringArray($figure, 'p.figure'), isset($figure_invert)));
}
// ###########
if (!empty($error)) {
$qb->andWhere('(pos.id_variation IS NULL AND (SELECT COUNT(*) FROM products_variations WHERE pos.id_product=products_variations.id_product) > 0)');
unset($fields, $name);
}
return $qb;
}
}

View File

@@ -0,0 +1,80 @@
<?php
use KupShop\AdminBundle\AdminList\BaseList;
use KupShop\AdminBundle\Util\ProductListFilter;
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
class productsPricesList extends BaseList
{
protected $template = 'list/products.prices.tpl';
protected $tableDef = [
'id' => 'pos.id',
'class' => 'getRowClass',
'fields' => [
'ID' => ['field' => 'pos.id', 'size' => 0.3, 'type' => 'productsOfSuppliers'],
'Produkt' => ['field' => 'p_title', 'size' => 1, 'type' => 'product', 'type_id' => 'p_id'],
'Varianta' => ['field' => 'pv_title', 'size' => 1],
'Dodavatel' => ['field' => 's.name', 'size' => 0.7],
'Sklad dodavatele' => ['field' => 'pos_in_store', 'size' => 0.4, 'class' => 'right'],
'Skladem u nás' => ['field' => 'in_store', 'size' => 0.2, 'class' => 'right'],
'Nákupní cena' => ['field' => 'product_price_buy', 'size' => 0.4, 'render' => 'renderPriceVat', 'spec' => 'COALESCE(pv.price_buy, p.price_buy) product_price_buy'],
'VOC Dod.' => ['field' => 'pos.price_buy', 'size' => 0.4, 'render' => 'renderPriceVat'],
'MOC Dod.' => ['field' => 'pos.price_sell', 'size' => 0.4, 'render' => 'renderPriceVat'],
'Základní' => ['field' => 'p.price', 'size' => 0.4, 'render' => 'renderPriceVat'],
'Prodejní' => ['field' => 'price_final', 'size' => 0.4, 'render' => 'renderPrice'],
'Běžná' => ['field' => 'p.price_common', 'size' => 0.4, 'render' => 'renderPrice'],
'Marže Dod.' => ['field' => 'marze', 'size' => 0.4, 'render' => 'renderPercents'],
'Nák. cena/Zákl' => ['field' => 'nakzakl', 'size' => 0.4, 'render' => 'renderPercents', 'spec' => '((COALESCE(pv.price, p.price) / COALESCE(pv.price_buy, p.price_buy) - 1) * 100) as nakzakl'],
'MOC Dod/Zákl' => ['field' => 'dodzakl', 'size' => 0.4, 'render' => 'renderPercents', 'spec' => '(((COALESCE(pv.price, p.price) / pos.price_sell) - 1) * 100) as dodzakl'],
'Poznámka' => ['field' => 'note', 'size' => 0.5],
],
];
protected $showAddItem = 'data[id_product]={productId}&data[id_variation]={variationId}';
public function getRowClass($values)
{
$price = $values['price'];
$discount = $values['discount'];
$vat = $values['vat'];
$price_buy = $values['price_buy'];
$price_sell = $values['price_sell'];
$class = [];
$price = calcPrice($price, $vat, $discount);
if ($price->lowerThan(calcPrice($price_buy, $vat, null))) { // setPrice($price_buy, null, $vat, "format=false"))
$class[] = 'up';
}
if ($price->comp(calcPrice($price_sell, $vat, null))) {
$class[] = 'down';
}
return join(' ', $class);
}
public function getQuery()
{
/** @var \KupShop\ElninoBundle\Query\QueryBuilder $qb */
$qb = sqlQueryBuilder()
->select('pos.id', 'pos.id ID', 'p.title p_title', 'pv.title pv_title', 's.name', 'pos.in_store AS pos_in_store', 'COALESCE(pv.in_store, p.in_store) AS in_store', 'COALESCE(pv.note, p.note) AS note', 'pos.price_buy', 'pos.price_sell', 'p.id as p_id', 'COALESCE(pv.price, p.price) as price', 'p.price_common', 'p.vat', 'p.discount',
'COALESCE(pv.price, p.price)*((100+v2.vat)/100)*((100-p.discount)/100) as price_final',
'(COALESCE(pv.price, p.price)*((100-p.discount)/100) - pos.price_buy)/(COALESCE(pv.price, p.price)*((100-p.discount)/100)) * 100 as marze',
)
->from('products', 'p')
->leftJoin('p', 'vats', 'v2', 'v2.id=p.vat')
->joinVariationsOnProducts()
->joinProductsOfSuppliers()
->leftJoin('pos', 'suppliers', 's', 'pos.id_supplier=s.id')
->where('COALESCE(pv.price_buy, p.price_buy) > 0 OR pos.price_buy > 0 OR pos.price_sell > 0')
->groupBy('p.id', 'pv.id', 'pos.id');
$filter = getVal('filter', null, []);
if (!empty($filter)) {
ServiceContainer::getService(ProductListFilter::class)->applyFilter($filter, $qb);
}
return $qb;
}
}

View File

@@ -0,0 +1,20 @@
<?php
use KupShop\AdminBundle\AdminList\BaseList;
class ProductsRelatedTypesList extends BaseList
{
protected $tableDef = [
'id' => 'id',
'fields' => [
'Název' => ['field' => 'name'],
],
];
public function getQuery()
{
$qb = sqlQueryBuilder()->select('*')->from('products_related_types');
return $qb;
}
}

View File

@@ -0,0 +1,31 @@
<?php
use KupShop\AdminBundle\AdminList\BaseList;
/**
* Created by PhpStorm.
* User: hanz
* Date: 12.6.14
* Time: 14:46.
*/
class ProductsVarLabelsList extends BaseList
{
protected $showMassEdit = true;
protected $tableName = 'products_variations_choices_labels';
protected ?string $tableAlias = 'pvcl';
protected $tableDef = [
'id' => 'pvcl.id',
'fields' => [
'label' => ['translate' => true, 'field' => 'pvcl.label', 'spec' => 'pvcl.label', 'fieldType' => BaseList::TYPE_STRING],
'ID' => ['field' => 'id', 'wpjAdmin' => true],
],
];
public function getQuery()
{
$qb = sqlQueryBuilder()->select('id')->from('products_variations_choices_labels', 'pvcl');
return $qb;
}
}

View File

@@ -0,0 +1,154 @@
<?php
namespace Admin\Lists;
use KupShop\AdminBundle\AdminList\BaseList;
use KupShop\CatalogBundle\Query\Search;
use KupShop\KupShopBundle\Util\HtmlBuilder\HTML;
use Query\Operator;
use Query\QueryBuilder;
class ProductsVarLabelsValuesList extends BaseList
{
use \AdminListSortable;
protected $pageDivide = 100;
protected $showMassEdit = true;
protected $tableName = 'products_variations_choices_values';
protected ?string $tableAlias = 'pvcv';
protected $template = 'listSortable.tpl';
protected $tableDef = [
'id' => 'pvcv.id',
'fields' => [
'sort' => ['translate' => true, 'spec' => 'sort as position', 'field' => 'pvcv.sort', 'size' => 0.5, 'render' => 'renderPosition', 'fieldType' => self::TYPE_POSITION],
'ID' => ['field' => 'pvcv.id', 'size' => 0.5],
'value' => ['translate' => true, 'field' => 'pvcv.value', 'fieldType' => BaseList::TYPE_STRING],
'code' => ['translate' => true, 'field' => 'pvcv.code', 'fieldType' => BaseList::TYPE_STRING],
'filter_url' => ['translate' => true, 'field' => 'pvcv.filter_url', 'fieldType' => BaseList::TYPE_STRING],
'title' => ['translate' => true, 'field' => 'pvcv.title', 'fieldType' => BaseList::TYPE_STRING],
'actions' => ['translate' => true, 'field' => 'pl.id', 'render' => 'renderActions'],
],
];
public function customizeTableDef($tableDef)
{
$tableDef = parent::customizeTableDef($tableDef);
if (!findModule(\Modules::INDEXED_FILTER)) {
unset($tableDef['fields']['filter_url'], $tableDef['fields']['title']);
}
return $tableDef;
}
public function getFilterQuery(): QueryBuilder
{
$qb = parent::getFilterQuery();
if ($parameterId = getVal('ID')) {
$qb->andWhere(Operator::equals(['id_label' => $parameterId]));
}
if ($param = getVal('searchTerm')) {
$params = [
['field' => 'value', 'match' => 'both'],
['field' => 'code', 'match' => 'both'],
];
if (findModule(\Modules::INDEXED_FILTER)) {
$params[] = ['field' => 'title', 'match' => 'both'];
$params[] = ['field' => 'filter_url', 'match' => 'both'];
}
$qb->andWhere(
Search::searchFields($param, $params, 'OR')
);
}
return $qb;
}
public function getQuery()
{
$id = getVal('ID');
$qb = parent::getQuery();
$qb
->leftJoin($this->tableAlias, 'products_variations_choices_labels', 'pvcl', 'pvcv.id_label = pvcl.id')
->andWhere(Operator::equals(['pvcv.id_label' => $id]))
->orderBy('sort');
$combinations = sqlQueryBuilder()
->select('COUNT(pvc.id_variation) as cnt')
->from('products_variations_combination', 'pvc')
->where('pvc.id_value = pvcv.id');
$qb->addSubselect($combinations, 'cnt');
return $qb;
}
public function renderActions(array $values): HTML
{
$listId = $values['id_label'] ?? null;
return HTML::create('div')
->class('btn-group')
->tag('a')
->attr('href', "javascript:nw('productsList', '', 'IDvv={$values['id']}&showOld=1')")
->class('btn btn-sm btn-secondary')
->text((string) ($values['cnt'] ?: '0'))
->end()
->tag('a')
->attr('href', "javascript:nw('productsVarLabels', '{$values['id']}', 'deleteValue')")
->attr('title', 'Smazat/Přesunout hodnotu jmenovky')
->class('btn btn-sm btn-warning')
->tag('span')
->class('bi bi-arrow-left-right')
->end()
->tag('a')
->attr('href', "launch.php?s=list.php&type=productsVarLabelsValues&ID={$listId}&acn=deleteValue&delete={$values['id']}")
->class('btn btn-sm btn-danger')
->tag('span')
->class('bi bi-trash')
->end()
->end()
->end();
}
public function handleDrag(): void
{
$item = getVal('moved_item');
$url = $_POST['url'] ?? null;
$parsed = [];
if ($url) {
parse_str($url, $parsed);
}
$extraWhere = '';
if ($parameterId = getVal('ID', $parsed)) {
$extraWhere = " AND id_label = {$parameterId}";
}
if ($item) {
$this->saveList($item, $this->tableName, 'sort', $extraWhere);
exit(json_encode(['result' => true]));
}
}
public function handleDeleteValue(): void
{
if ($valueId = getVal('delete')) {
sqlQueryBuilder()
->delete($this->tableName)
->where(Operator::equals(['id' => $valueId]))
->execute();
}
redirect($_SERVER['HTTP_REFERER']);
}
}
return ProductsVarLabelsValuesList::class;

349
admin/lists/ReviewsList.php Normal file
View File

@@ -0,0 +1,349 @@
<?php
use KupShop\AdminBundle\AdminList\BaseList;
use KupShop\AdminBundle\AdminList\FiltersStorage;
use KupShop\AdminBundle\Query\Invert;
use KupShop\CatalogBundle\Util\ReviewsUtil;
use KupShop\KupShopBundle\Util\HtmlBuilder\HTML;
use Query\Operator;
/**
* Created by PhpStorm.
* User: hanz
* Date: 3.6.14
* Time: 12:30.
*/
class ReviewsList extends BaseList
{
use FiltersStorage;
protected $template = 'list/reviews.tpl';
protected $pageDivide = 200;
protected $index = -1;
protected $tableDef = [
'id' => 'id',
'fields' => [
'E-mail' => ['field' => 'email', 'render' => 'renderEmail', 'size' => 0.7],
'Jméno' => ['field' => 'user_name', 'render' => 'renderObject', 'size' => 0.4, 'visible' => 'N'],
'Objednávka' => ['field' => 'id_order', 'type' => 'orders', 'type_id' => 'id_order', 'size' => 0.5, 'visible' => 'N'],
'Produkt' => ['field' => 'product_title', 'type' => 'product', 'type_id' => 'id_product'],
'Komentář' => ['field' => 'summary', 'render' => 'renderReview', 'size' => 1.7],
'Datum přidání' => ['field' => 'date', 'render' => 'renderDateTime', 'size' => 0.6],
'Hodnocení' => ['field' => 'rating', 'render' => 'renderRating', 'size' => 0.5],
'Ověřená' => ['field' => 'verified', 'spec' => '(r.id_order IS NOT NULL || r.source IS NOT NULL) as verified', 'render' => 'renderVerified', 'size' => 0.4],
'Stav' => ['field' => 'figure', 'render' => 'renderFigured', 'size' => 0.5, 'class' => 'review-figure'],
'Top' => ['field' => 'figure', 'render' => 'renderTop', 'class' => 'hiddenTooltip', 'size' => 0.4],
'Zdroj' => ['field' => 'source', 'render' => 'renderSource', 'size' => 0.5, 'visible' => 'N'],
'Zamítnout' => ['field' => 'figure', 'render' => 'renderDelete', 'size' => 0.4],
'Odpověď' => ['field' => 'response', 'size' => 2, 'visible' => 'N'],
],
];
protected $orderParam = [
'sort' => 'Datum přidání',
'direction' => 'DESC',
];
public function __construct()
{
if (!empty($_GET['type_list']) && $_GET['type_list'] == 'showMostRated') {
$this->tableDef = [
'id' => 'id',
'fields' => [
'Produkt' => ['field' => 'product_title', 'type' => 'product', 'type_id' => 'id_product'],
'Počet hodnocení' => ['field' => 'review'],
'Průměrné hodnocení' => ['field' => 'rating', 'render' => 'renderRating'],
],
];
}
if (!empty($_GET['type_list']) && $_GET['type_list'] != 'ShowNotConfirmed' && $_GET['type_list'] != 'ShowConfirmed') {
unset($this->tableDef['fields']['Top']);
}
}
public function renderEmail($values, $column)
{
$value = $this->getListRowValue($values, $column['field']);
if (empty($value) && ($data = $values['data'])) {
$data = json_decode($data, true);
$value = $data['email'] ?? '';
}
return $value;
}
public function renderVerified($values, $column)
{
$value = 'N';
if (!empty($values['id_order']) || !empty($values['source'])) {
$value = 'Y';
}
return $this->renderBoolean(['verified' => $value], $column);
}
public function renderObject($values, $column)
{
$value = $this->getListRowValue($values, $column['field']);
if (empty($value)) {
return $values['name'];
} else {
$output = HTML::create('a');
$output
->attr('href', "javascript:nw('user', '{$values['id_user_name']}')")
->text(' $value');
}
}
public function renderRating($values, $column)
{
$rating = HTML::create('span');
for ($i = 0; $i < $values['rating']; $i++) {
$rating->tag('i')
->attr('class', 'glyphicon glyphicon-star rating-full')
->end();
}
for ($i = 0; $i < intval(5 - $values['rating']); $i++) {
$rating->tag('i')
->attr('class', 'glyphicon glyphicon-star rating-empty')
->end();
}
return $rating;
}
public function renderFigured($values, $column)
{
if (array_key_exists($values['figure'], ReviewsUtil::$rank)) {
return translate(ReviewsUtil::$rank[$values['figure']]);
}
return $values['figure'];
}
public function renderSource($values, $column)
{
return ReviewsUtil::$sources[$values['source']] ?? 'interní';
}
public function renderReview($values, $column)
{
$output = HTML::create('span');
if (!empty($values['pros'])) {
$output
->tag('strong')
->text('Pro: ')
->end()
->text($values['pros'])
->tag('br')
->end();
}
if (!empty($values['cons'])) {
$output
->tag('strong')
->text('Proti: ')
->end()
->text($values['cons'])
->tag('br')
->end();
}
if (!empty($values['summary'])) {
$output
->tag('strong')
->text('Shrnutí: ')
->end()
->text($values['summary'])
->tag('br')
->end();
}
return $output;
}
public function renderDelete($values, $column)
{
return HTML::create('a')
->attr('class', 'btn-sm btn btn-danger')
->attr('data-form-delete', '')
->attr('title', 'Zamítnout hodnocení')
->tag('input')
->attr('name', "data[reviews][{$values['id']}][delete]")
->attr('value', '')
->attr('data-form-delete-input', $values['id'])
->attr('type', 'hidden')
->end()
->tag('span')
->attr('class', 'bi bi-slash-circle')
->end();
}
public function renderTop($values, $column)
{
return HTML::create('a')
->attr('class', 'btn-sm btn btn-success review-top'.($values['figure'] == ReviewsUtil::RANK_TOP ? ' disabled' : ''))
->attr('data-form-top', '')
->attr('title', 'Označit jako TOP (zároveň schválí hodnocení)')
->tag('input')
->attr('name', "data[reviews][{$values['id']}][top]")
->attr('value', '')
->attr('data-form-top-input', $values['id'])
->attr('type', 'hidden')
->end()
->tag('span')
->attr('class', 'bi bi-hand-thumbs-up')
->end();
}
public function handle()
{
parent::handle();
$data = getVal('data');
if (!empty($data['reviews'])) {
foreach ($data['reviews'] as $review_id => $review) {
if ($review['delete']) {
$this->updateSQL('reviews', ['figure' => 0], ['id' => $review_id]);
} elseif ($review['top']) {
$this->updateSQL('reviews', ['figure' => 5], ['id' => $review_id]);
} elseif (getVal('Submit') == 'Schválit vše') {
$this->updateSQL('reviews', ['figure' => 3], ['id' => $review_id]);
}
}
}
}
public function getQuery()
{
$qb = sqlQueryBuilder()
->select('r.*', 'u.id as id_user_name', 'CONCAT(u.name," ", u.surname) as user_name', 'u.email',
'CONCAT(p.title, " ", IF(pv.title IS NULL,"", pv.title)) as product_title')
->from('reviews', 'r')
->leftJoin('r', 'users', 'u', 'r.id_user=u.id')
->leftJoin('r', 'products', 'p', 'p.id=r.id_product')
->leftJoin('r', 'products_variations', 'pv', 'pv.id=r.id_product_variation');
if (!empty($_GET['type_list'])) {
switch ($_GET['type_list']) {
case 'ShowNotConfirmed':
$qb->where('r.figure = 1');
break;
case 'ShowConfirmed':
$qb->where('r.figure=3 OR r.figure=5');
break;
case 'showTop':
$qb->where('r.figure=5');
break;
case 'showMostRated':
$qb = sqlQueryBuilder()
->select('r.id', 'r.id_product', 'COUNT(r.rating) as review', 'AVG(r.rating) as rating', 'CONCAT(p.title, " ", IF(pv.title IS NULL,"", pv.title)) as product_title')
->from('reviews', 'r')
->leftJoin('r', 'products', 'p', 'p.id=r.id_product')
->leftJoin('r', 'products_variations', 'pv', 'pv.id=r.id_product_variation')
->where('r.figure > 1')
->groupBy('r.id_product')
->orderBy('review DESC');
$this->orderParam = [
'sort' => 'Počet hodnocení',
'direction' => 'DESC',
];
break;
}
} else {
$review = getVal('review');
if (!empty($review)) {
$search = get_search_query(
$review,
[
['field' => 'r.pros', 'match' => 'both'],
['field' => 'r.cons', 'match' => 'both'],
['field' => 'r.summary', 'match' => 'both'],
]
);
$qb->andWhere($search['where']);
$qb->addParameters($search['data']);
}
$email = getVal('email');
if (!empty($email)) {
$search = get_search_query(
$email,
[
['field' => 'u.email', 'match' => 'both'],
]
);
$qb->andWhere($search['where']);
$qb->addParameters($search['data']);
}
$dateFrom = getVal('dateFrom');
$dateTo = getVal('dateTo');
if (!empty($dateFrom) || !empty($dateTo)) {
if (!empty($dateFrom)) {
$dateFrom = new DateTime($dateFrom);
$dateFrom->setTime(0, 0, 0);
$qb->andWhere('r.date >= :date_from')->setParameter('date_from', $dateFrom, 'datetime');
}
if (!empty($dateTo)) {
$dateTo = new DateTime($dateTo);
$dateTo->setTime(23, 59, 59);
$qb->andWhere('r.date <= :date_to')->setParameter('date_to', $dateTo, 'datetime');
}
}
$figure = getVal('figure');
$figure_invert = getVal('figure_invert');
if (isset($figure) && $figure != '') {
$qb->andWhere(Invert::checkInvert(Operator::inIntArray((array) $figure, 'r.figure'), isset($figure_invert)));
} else {
// skip declined reviews by default
$qb->andWhere('r.figure != 0');
}
$ratingFrom = getVal('ratingFrom');
$ratingTo = getVal('ratingTo');
if (!empty($ratingFrom) || !empty($ratingTo)) {
if (!empty($ratingFrom) && intval($ratingFrom)) {
$qb->andWhere('r.rating >= :rating_from')->setParameter('rating_from', intval($ratingFrom), 'integer');
}
if (!empty($ratingTo) && intval($ratingTo)) {
$qb->andWhere('r.rating <= :rating_to')->setParameter('rating_to', intval($ratingTo), 'integer');
}
}
if (!empty($_GET['productId'])) {
$qb->andWhere(Operator::equals(['r.id_product' => $_GET['productId']]));
if (!empty($_GET['variationId'])) {
$qb->andWhere(Operator::equals(['r.id_product_variation' => $_GET['variationId']]));
}
} elseif (!empty($_GET['productId_text'])) {
$search = get_search_query(
$_GET['productId_text'],
[
['field' => 'p.title', 'match' => 'both'],
]
);
$qb->andWhere($search['where']);
$qb->addParameters($search['data']);
}
$response = getVal('response');
$response_invert = getVal('response_invert');
if (!empty(getVal('response'))) {
array_map(function ($x) use ($qb, $response_invert) {
if ($x == 'Y') {
$qb->andWhere(Invert::checkInvert(Operator::isNotNull('response'), isset($response_invert)));
} elseif ($x == 'N') {
$qb->andWhere(Invert::checkInvert(Operator::isNull('response'), isset($response_invert)));
}
}, $response);
}
}
return $qb;
}
}

View File

@@ -0,0 +1,660 @@
<?php
use KupShop\AdminBundle\AdminList\BaseList;
use KupShop\AdminBundle\AdminListMassEdit\SectionsListMassEdit;
use KupShop\CatalogBundle\Util\SectionUtil;
use KupShop\I18nBundle\Admin\Util\ListTranslationsFigureBadges;
use KupShop\KupShopBundle\Config;
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
use KupShop\KupShopBundle\Util\HtmlBuilder\HTML;
use Query\Operator;
class SectionsList extends BaseList
{
use \KupShop\AdminBundle\Util\CategoryTree;
use ListTranslationsFigureBadges;
protected $template = 'list/sections.tpl';
protected $tableName = 'sections';
protected ?string $tableAlias = 's';
protected $showMassEdit = true;
protected $pageDivide = 9999;
protected $tableDef = [
'id' => 's.id',
'fields' => [
'Popis' => ['field' => 'descr', 'render' => 'renderHTML', 'class' => 'alignLeft', 'size' => 3],
'visibility' => ['translate' => true, 'field' => 'figure', 'render' => 'renderVisibility', 'visible' => 'N', 'fieldType' => SectionsList::TYPE_LIST],
'Feed H/G/S/GL' => ['field' => 'join_feed_heureka', 'render' => 'getFeeds', 'class' => 'columnFeeds', 'size' => 2],
'priority' => ['translate' => true, 'field' => 'priority', 'render' => 'renderPriority', 'size' => 1, 'visible' => 'N', 'fieldType' => SectionsList::TYPE_LIST],
'Heureka' => ['field' => 'join_feed_heureka', 'render' => 'renderBoolean', 'visible' => 'N', 'fieldType' => SectionsList::TYPE_LIST_AUTOCOMPLETE, 'fieldOptions' => ['autocomplete' => 'feed_heureka', 'table' => 'kupshop_shared.feed_heureka', 'field' => "CONCAT(name, ' - ' ,category_text)"]],
'Heureka SK' => ['field' => 'join_feed_heureka_sk', 'render' => 'renderBoolean', 'visible' => 'N', 'fieldType' => SectionsList::TYPE_LIST_AUTOCOMPLETE, 'fieldOptions' => ['autocomplete' => 'feed_heureka_sk', 'table' => 'kupshop_shared.feed_heureka_sk', 'field' => "CONCAT(name, ' - ' ,category_text)"]],
'Google' => ['field' => 'join_feed_google', 'render' => 'renderBoolean', 'visible' => 'N', 'fieldType' => SectionsList::TYPE_LIST_AUTOCOMPLETE, 'fieldOptions' => ['autocomplete' => 'feed_google', 'table' => 'kupshop_shared.feed_google', 'field' => "CONCAT(name, ' - ' ,category_text)"]],
'Seznam' => ['field' => 'join_feed_seznam', 'render' => 'renderBoolean', 'visible' => 'N', 'fieldType' => SectionsList::TYPE_LIST_AUTOCOMPLETE, 'fieldOptions' => ['autocomplete' => 'feed_seznam', 'table' => 'kupshop_shared.feed_seznam', 'field' => "CONCAT(name, ' - ' ,category_text)"]],
'Glami' => ['field' => 'join_feed_glami', 'render' => 'renderBoolean', 'visible' => 'N', 'fieldType' => SectionsList::TYPE_LIST_AUTOCOMPLETE, 'fieldOptions' => ['autocomplete' => 'feed_glami', 'table' => 'kupshop_shared.feed_glami', 'field' => "CONCAT(name, ' - ' ,category_text)"]],
'orderby' => ['translate' => true, 'field' => 'orderby', 'render' => 'renderOrderBy', 'visible' => 'N', 'size' => 1.5, 'fieldType' => SectionsList::TYPE_LIST],
'orderdir' => ['translate' => true, 'field' => 'orderdir', 'render' => 'renderOrderDir', 'visible' => 'N', 'size' => 1.5, 'fieldType' => SectionsList::TYPE_LIST],
'Příznak' => ['field' => 'flags', 'render' => 'renderFlags', 'class' => 'columnCampaigns', 'size' => 1],
'Podsekce' => ['field' => 'subsection', 'render' => 'getSubsection', 'class' => 'alignRight hidden-label overflow-visible columnBtns', 'size' => 1],
'redirect_url' => ['translate' => true, 'field' => 'redirect_url', 'visible' => 'N', 'fieldType' => SectionsList::TYPE_STRING, 'size' => 1],
],
'class' => null,
];
protected $showExport = false;
private $openedSections;
protected $additionalData;
protected array $sections = [];
private ?array $slidersCache = null;
protected function getSectionUtil(): SectionUtil
{
static $util = null;
if (!$util) {
$util = ServiceContainer::getService(SectionUtil::class);
}
return $util;
}
protected function getSliderUtil(): ?KupShop\ContentBundle\Util\SliderUtil
{
static $sliderUtil = null;
return $sliderUtil ??= (
findModule(\Modules::SLIDERS)
? ServiceContainer::getService(\KupShop\ContentBundle\Util\SliderUtil::class)
: null
);
}
public function handleGenerateVirtualSections()
{
$sectionUtil = $this->getSectionUtil();
$sectionUtil->generateVirtualSections();
$this->returnOK('Přegenerováno');
}
public function customizeTableDef($tableDef)
{
ini_set('memory_limit', '256M');
$tableDef = parent::customizeTableDef($tableDef);
$cfg = Config::get();
if (findModule(\Modules::TRANSLATIONS)) {
$tableDef['fields']['translationsFigure'] = $this->getTranslationsFigureField(
translationClass: \KupShop\I18nBundle\Translations\SectionsTranslation::class,
column: ['translation_section' => 'translations'],
);
}
$tableDef['fields']['priority']['fieldOptions'] = [
'-1' => translate('priority_minor', 'sections'),
'0' => translate('priority_normal', 'sections'),
'1' => translate('priority_major', 'sections'),
];
$tableDef['fields']['visibility']['fieldOptions'] = [
'Y' => translate('figureY', 'sections'),
'N' => translate('figureN', 'sections'),
'O' => translate('figureO', 'sections'),
];
$tableDef['fields']['orderby']['fieldOptions'] = [
'date' => translate('orderby_date', 'sections'),
'title' => translate('orderby_title', 'sections'),
'price' => translate('orderby_price', 'sections'),
'store' => translate('orderby_store', 'sections'),
'sell' => translate('orderby_sell', 'sections'),
'code' => translate('orderby_code', 'sections'),
'discount' => translate('orderby_discount', 'sections'),
'soldPrice' => translate('orderby_soldPrice', 'sections'),
'storeValue' => translate('orderby_storeValue', 'sections'),
];
$tableDef['fields']['orderdir']['fieldOptions'] = [
'ASC' => translate('orderdir_asc', 'sections'),
'DESC' => translate('orderdir_desc', 'sections'),
];
if (findModule(Modules::INDEXED_FILTER)) {
$tableDef['fields']['filterUrl'] = [
'translate' => true, 'field' => 's.filter_url', 'visible' => 'N', 'fieldType' => SectionsList::TYPE_STRING, 'size' => 1,
];
$tableDef['fields']['title'] = [
'translate' => true, 'field' => 'section_filter_title', 'visible' => 'N', 'size' => 1, 'fieldType' => SectionsList::TYPE_STRING,
];
}
if (findModule(Modules::PRODUCTS_SECTIONS, 'custom_url')) {
$tableDef['fields']['sectionUrl'] = [
'translate' => true, 'field' => 'section_custom_url', 'visible' => 'N', 'fieldType' => SectionsList::TYPE_STRING, 'size' => 1,
];
}
$tableDef['fields']['Popis']['spec'] = function (Query\QueryBuilder $qb) {
$subSelect = sqlQueryBuilder()->select('LEFT(STRIP_TAGS(b.content), 200)')
->from('blocks', 'b')
->where('b.id_root = s.id_block AND b.content IS NOT NULL AND b.content != "" ')
->orderBy('b.position')
->setMaxResults(1);
$qb->addSubselect($subSelect, 'descr');
};
$tableDef['fields']['Heureka']['spec'] = function (Query\QueryBuilder $qb) {
$qb->addSelect('f_h.id as join_feed_heureka')
->leftJoin('s', 'kupshop_shared.feed_heureka', 'f_h', 'f_h.id=s.feed_heureka');
};
$tableDef['fields']['Heureka SK']['spec'] = function (Query\QueryBuilder $qb) {
$qb->addSelect('f_hsk.id as join_feed_heureka_sk')
->leftJoin('s', 'kupshop_shared.feed_heureka_sk', 'f_hsk', 'f_hsk.id=s.feed_heureka_sk');
};
$tableDef['fields']['Google']['spec'] = function (Query\QueryBuilder $qb) {
$qb->addSelect('f_g.id as join_feed_google')
->leftJoin('s', 'kupshop_shared.feed_google', 'f_g', 'f_g.id=s.feed_google');
};
$tableDef['fields']['Seznam']['spec'] = function (Query\QueryBuilder $qb) {
$qb->addSelect('f_s.id as join_feed_seznam')
->leftJoin('s', 'kupshop_shared.feed_seznam', 'f_s', 'f_s.id=s.feed_seznam');
};
$tableDef['fields']['Glami']['spec'] = function (Query\QueryBuilder $qb) {
$qb->addSelect('f_gl.id IS NOT NULL as join_feed_glami')
->leftJoin('s', 'kupshop_shared.feed_glami', 'f_gl', 'f_gl.id=s.feed_glami');
};
$tableDef['fields']['Feed H/G/S/GL']['spec'] = function (Query\QueryBuilder $qb) use ($tableDef) {
$qb->addSelect($tableDef['fields']['Heureka']['spec']);
$qb->addSelect($tableDef['fields']['Google']['spec']);
$qb->addSelect($tableDef['fields']['Seznam']['spec']);
$qb->addSelect($tableDef['fields']['Glami']['spec']);
};
if (findModule(\Modules::SLIDERS)) {
$positions = \KupShop\ContentBundle\Util\SliderUtil::getPositions();
foreach ($positions as $position => $positionName) {
$tableDef['fields']["{$positionName} banner"] = [
'spec' => "JSON_EXTRACT(sliders_positions.positions, '$.{$position}') AS {$position}_slider_name",
'field' => "{$position}_slider_name",
];
}
}
return $tableDef;
}
public function getColumns()
{
$table = parent::getColumns();
// add first column and fix positions
foreach ($table['fields'] as $key => $value) {
$value['position']++;
}
$table['fields'] = array_merge([
'Sekce' => [
'label' => 'Název',
'field' => 'name', 'render' => 'getTitle', 'class' => 'alignLeft', 'size' => 4, 'position' => '0',
'visible' => 'Y', 'multiplier' => '1', 'type_id' => $table['id'], 'type' => $GLOBALS['type'],
],
], $table['fields']);
return $table;
}
public function renderVisibility($values, $column)
{
if ($values['figure'] === 'O') {
return $this->renderIcon('warning');
}
return $this->renderBoolean($values, $column);
}
public function renderFlags($values, $column)
{
$badges = $this->getSectionUtil()->getBadges(
figure: $values['figure'],
virtual: $values['virtual'],
showInSearch: $values['show_in_search']
);
return array_map(
fn (array $badge) => $this->renderBadge(
translate($badge['translate_key'], 'sections'),
$badge['class'],
$badge['icon']
),
$badges,
);
}
public function renderPriority($values, $column)
{
switch ($values[$column['field']]) {
case -1:
return translate('priority_minor', 'sections');
case 0:
return translate('priority_normal', 'sections');
case 1:
return translate('priority_major', 'sections');
}
return '';
}
public function renderOrderBy($values, $column)
{
if ($orderby = $values['orderby'] ?? null) {
return translate('orderby_'.$orderby, 'sections');
}
return '';
}
public function renderOrderDir($values, $column)
{
if ($orderdir = $values['orderdir'] ?? null) {
return translate('orderdir_'.strtolower($orderdir), 'sections');
}
return '';
}
public function getListRowValue($values, $field, $default = null)
{
$field_name = $this->getFieldArrayName($field);
if (empty($values[$field_name])) {
return $this->additionalData[$values['id']][$field_name] ?? $default;
}
return $values[$field_name];
}
public function getTitle($values, $column)
{
if ($values['id'] == 0) {
return HTML::create('strong')->attr('class', 'text-dark')
->text($this->getListRowValue($values, $column['field']));
}
return [
HTML::create('span')
->class('drag-drop-mover')
->tag('i')
->class('bi bi-arrows-move handle')
->end(),
HTML::create('span')
->class('bi bi-dash-circle opener '
.($this->openedSections == 'all' || in_array($values['id'], $this->openedSections) ? ' ' : 'plus ')
.($values['children_count'] > 0 ? '' : 'disabled')),
HTML::create('strong')
->attr('class', 'text-dark')
->text($this->getListRowValue($values, $column['field'])),
];
}
public function getFeeds($values, $column)
{
$return = [];
$return[] = $this->renderBoolean($values, ['field' => 'join_feed_heureka'], 'Heureka');
$return[] = $this->renderBoolean($values, ['field' => 'join_feed_google'], 'Google');
$return[] = $this->renderBoolean($values, ['field' => 'join_feed_seznam'], 'Seznam');
$return[] = $this->renderBoolean($values, ['field' => 'join_feed_glami'], 'Glami');
// add space between icons
/** @var HTML $ret */
foreach ($return as &$ret) {
$ret = $ret->tag('span')->attr('style', 'padding-right:4px')->end();
}
return $return;
}
public function getTemplate()
{
if (getVal('root')) {
return 'list/sections.ajax.tpl';
}
return parent::getTemplate();
}
public function getSubsection($values)
{
if ($values['id'] == 0) {
$result = HTML::create('a')
->attr('class', 'btn btn-sm btn-block btn-success')
->attr('title', 'Přidat sekci')
->attr('href', 'javascript:nw("sections", '.null.');')
->tag('span')
->class('bi bi-plus-lg m-r-1')
->end();
return $result->text('Přidat sekci');
}
return HTML::create('a')
->attr('class', 'btn btn-sm btn-success')
->attr('title', 'Přidat podsekci')
->attr('href', 'javascript:nw("sections", "", "&sections[]='.$values['id'].'");')
->tag('span')
->class('bi bi-plus-lg')
->end();
}
public function handleDrag()
{
$tree = getVal('tree');
if ($tree) {
sqlGetConnection()->transactional(function () use ($tree) {
$old_id_topsection = returnSQLResult('SELECT id_topsection FROM sections_relation WHERE id_section=:id_section', ['id_section' => $tree['id']]);
$compare = ' >= ';
if (!empty($tree['after'])) {
$id_anchor = $tree['after'];
$compare = ' > ';
} elseif (!empty($tree['before'])) {
$id_anchor = $tree['before'];
} else {
$id_anchor = null;
}
if ($id_anchor) {
$anchor = sqlFetchAssoc(sqlQuery('SELECT * FROM sections_relation WHERE id_section=:id_section', ['id_section' => $id_anchor]));
} else {
// Insert as the only child
$anchor = ['position' => 0, 'id_topsection' => $tree['target']];
}
// Check cycle
$cycling = $this->checkSubSections($this->getCategoryById($tree['id'])['children'], $anchor['id_topsection']);
if ($cycling) {
header('HTTP/1.1 500 Error');
exit('Nelze zvolit jako nadřazenou sekci některou z podsekcí!');
}
sqlQuery('DELETE FROM sections_relation WHERE id_section=:id_section', ['id_section' => $tree['id']]);
sqlQueryBuilder()->update('sections_relation')
->set('position', 'position+2')
->where(Operator::equalsNullable(['id_topsection' => $anchor['id_topsection']]))
->andWhere("position {$compare} :anchor_position")
->setParameter('anchor_position', $anchor['position'])
->execute();
sqlQueryBuilder()->insert('sections_relation')
->directValues([
'id_section' => $tree['id'],
'id_topsection' => $anchor['id_topsection'],
'position' => $anchor['position'] + 1,
])
->execute();
self::orderTreeLevel($anchor['id_topsection']);
if ($anchor['id_topsection'] != $old_id_topsection) {
self::orderTreeLevel($old_id_topsection);
}
});
MenuSectionTree::invalidateCache();
exit('OK');
}
exit('Err');
}
public static function orderTreeLevel($id_topsection)
{
if (empty($id_topsection)) {
$where = 'id_topsection IS NULL';
} else {
$where = "id_topsection = {$id_topsection}";
}
$SQL = sqlQuery('SELECT id_section, position
FROM '.getTableName('sections_relation').' sr
LEFT JOIN '.getTableName('sections')." s ON s.id=sr.id_section
WHERE {$where}
ORDER BY sr.position, s.name");
foreach ($SQL as $index => $row) {
if ($row['position'] != $index) {
sqlQuery('UPDATE '.getTableName('sections_relation')." SET position={$index} WHERE id_section={$row['id_section']} AND {$where}");
}
}
}
public function renderCell($values, $column, $tooltip = '')
{
$value = parent::renderCell($values, $column, $tooltip);
if (in_array($column['field'], ['join_feed_heureka', 'join_feed_heureka_sk', 'join_feed_seznam', 'join_feed_google', 'join_feed_glami'])) {
return (bool) $value;
}
return $value;
}
public function getQuery()
{
$qb = $this->getSectionsQueryBuilder()
->andWhere(Operator::inIntArray($this->getFilterIds(), 's.id'));
return $qb;
}
public function getFilterQuery(): Query\QueryBuilder
{
$qb = parent::getFilterQuery()
->leftJoin('s', 'sections_relation', 'sr', 's.id = sr.id_section');
if ($rootId = getVal('root') ?? false) {
$qb->andWhere(Operator::equals(['sr.id_topsection' => $rootId]));
} else {
$qb->andWhere(
Operator::orX(
Operator::equals(['sr.id_topsection' => 0]),
'sr.id_topsection IS NULL'
)
);
}
return $qb;
}
public function get_vars()
{
$vars = parent::get_vars();
$vars['openedSections'] = $this->getOpenedSections();
return $vars;
}
public function getSQL(Query\QueryBuilder $qb)
{
$result = parent::getSQL($qb);
$sections = $this->loadSubSections(
sqlFetchAll($result['SQL'], 'id')
);
$result['SQL'] = $sections;
return $result;
}
protected function getDefaultOrder()
{
return [
'sort' => 'sr.position',
'direction' => 'ASC',
];
}
protected function getSectionsQueryBuilder(): Query\QueryBuilder
{
$qb = sqlQueryBuilder()
->select('s.*')
->from('sections', 's')
->leftJoin('s', 'sections_relation', 'sr', 's.id = sr.id_section')
->groupBy('s.id')
->orderBy('sr.position');
$childrenCountSubQuery = sqlQueryBuilder()
->select('COUNT(id_section)')
->from('sections_relation')
->where('id_topsection = s.id');
$qb->addSubselect($childrenCountSubQuery, 'children_count');
if (findModule(Modules::INDEXED_FILTER)) {
$qb->addSelect('s.title as section_filter_title, s.filter_url');
}
if (findModule(Modules::PRODUCTS_SECTIONS, 'custom_url')) {
$qb->addSelect('s.url as section_custom_url');
}
if (findModule(\Modules::SLIDERS)) {
$sliderPositions = sqlQueryBuilder()->select('sis.id_section AS id', 'CONCAT("{", GROUP_CONCAT( DISTINCT CONCAT(\'"\', sis.position, \'": "\', sliders.name, \'"\') SEPARATOR \', \'), "}") AS positions')
->from('sliders_in_sections', 'sis')
->leftJoin('sis', 'sliders', 'sliders', 'sis.id_slider = sliders.id')
->groupBy('sis.id_section');
$qb->leftJoinSubQuery('s', $sliderPositions, 'sliders_positions', 's.id = sliders_positions.id');
}
return $qb;
}
private function loadSubSections(array $rootSections): array
{
$openedSections = $this->getOpenedSections();
if (empty($openedSections)) {
return $rootSections;
}
$sectionUtil = ServiceContainer::getService(SectionUtil::class);
if ($openedSections === 'all') {
$sectionIds = call_user_func_array('array_merge', array_map(
fn ($x) => $sectionUtil->getDescendantCategories($x['id'], false),
$rootSections
));
} else {
$sectionIds = array_keys($rootSections);
foreach ($openedSections as $openedSection) {
$sectionIds = array_merge($sectionIds, $sectionUtil->getDescendantCategories($openedSection, false));
}
}
$qb = $this->getSectionsQueryBuilder()
->addSelect('sr.id_topsection')
->andWhere(
Operator::orX(
Operator::inIntArray($sectionIds, 'sr.id_topsection'),
'sr.id_topsection IS NULL'
)
)
->orderBy('FIELD(s.id, :sectionIds)')
->setParameter('sectionIds', $sectionIds, \Doctrine\DBAL\Connection::PARAM_INT_ARRAY);
$qb = $this->evaluateColumnClosures($qb);
return $this->buildSectionTree(
sqlFetchAll($qb->execute(), 'id')
);
}
// zbuildim strom sekci za pomoci referenci, protoze je to mnohem rychlejsi, jak kdyz se to buildi rekurzivne
private function buildSectionTree(array $sections): array
{
$tree = [];
$references = [];
foreach ($sections as $id => &$section) {
// Add the node to our associative array using its ID as key
$references[$id] = &$section;
// Add empty placeholder for children
$section['children'] = [];
// If it's a root node, we add it directly to the tree
if (empty($section['id_topsection'])) {
$tree[$id] = &$section;
} else {
// It was not a root node, add this node as a reference in the parent.
$references[$section['id_topsection']]['children'][$id] = &$section;
}
}
return $tree;
}
private function getOpenedSections()
{
if ($this->openedSections !== null) {
return $this->openedSections;
}
$openedSectionsGet = getVal('opened') ?? [];
$openedSectionsCookie = getVal('products_list_opened_sections', $_COOKIE, false);
if (isset($_COOKIE['products_list_opened_sections'])) {
unset($_COOKIE['products_list_opened_sections']);
setcookie('products_list_opened_sections', '', -1, '/');
}
$this->openedSections = [];
if ($openedSectionsGet != 'all') {
$this->openedSections += ($openedSectionsGet) ? json_decode_strict($openedSectionsGet) : [];
$this->openedSections += ($openedSectionsCookie) ? json_decode_strict($openedSectionsCookie) : [];
} else {
$this->openedSections = 'all';
}
return $this->openedSections;
}
public function customizeMassTableDef($tableDef)
{
$tableDef = parent::customizeMassTableDef($tableDef);
if (findModule(\Modules::SLIDERS)) {
$positions = \KupShop\ContentBundle\Util\SliderUtil::getPositions();
foreach ($positions as $position => $positionName) {
$tableDef['fields']["{$positionName} banner"] = [
'fieldType' => SectionsListMassEdit::TYPE_SLIDERS,
'sliderPosition' => $position,
'field' => 'sliders_'.$position,
'size' => 1.25,
];
}
$badges = $tableDef['fields']['Příznak'];
unset($tableDef['fields']['Příznak']);
$tableDef['fields']['Příznak'] = $badges;
$tableDef['fields']['Popis']['size'] = 2;
}
unset($tableDef['fields']['Feed H/G/S/GL']);
return $tableDef;
}
}

View File

@@ -0,0 +1,29 @@
<?php
use KupShop\AdminBundle\AdminList\BaseList;
class SlidersList extends BaseList
{
protected $showMassEdit = true;
protected $tableName = 'sliders';
protected ?string $tableAlias = 's';
protected $tableDef = [
'id' => 's.id',
'fields' => [
'name' => ['translate' => true, 'field' => 's.name', 'spec' => 's.name', 'size' => 2, 'fieldType' => BaseList::TYPE_STRING],
'images' => ['translate' => true, 'field' => 'images'],
'ID' => ['field' => 'id', 'wpjAdmin' => true],
'label' => ['translate' => true, 'field' => 's.label', 'spec' => 's.label', 'wpjAdmin' => true, 'visible' => 'N', 'fieldType' => BaseList::TYPE_STRING],
'size' => ['translate' => true, 'field' => 's.size', 'spec' => 's.size', 'wpjAdmin' => true, 'visible' => 'N', 'fieldType' => BaseList::TYPE_STRING],
],
];
public function getQuery()
{
$qb = sqlQueryBuilder()->select('s.*', 'COUNT(si.id) as images')->from('sliders', 's')->leftJoin('s', 'sliders_images', 'si', 's.id = si.id_slider')->groupBy('s.id ');
return $qb;
}
}

509
admin/lists/StockInList.php Normal file
View File

@@ -0,0 +1,509 @@
<?php
use KupShop\AdminBundle\AdminList\BaseList;
use KupShop\AdminBundle\AdminList\FiltersStorage;
use KupShop\AdminBundle\Util\Stats\StoreDataLoader;
use KupShop\ElninoBundle\Query\QueryBuilder;
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
use KupShop\KupShopBundle\Util\Excel\ExcelGenerator;
use KupShop\KupShopBundle\Util\Excel\ExcelHeaderBuilder;
use KupShop\KupShopBundle\Util\HtmlBuilder\HTML;
use PhpOffice\PhpSpreadsheet\Cell\DataType;
use Query\Operator;
class StockInList extends BaseList
{
use FiltersStorage;
protected $orderParam = [
'sort' => 'ID',
'direction' => 'DESC',
];
protected $template = 'list/stockIn.tpl';
protected $tableDef = [
'id' => 's.id',
'class' => 'getRowClass',
'fields' => [
'ID' => ['field' => 's.number', 'render' => 'renderNumber'],
'supplier' => ['translate' => true, 'field' => 'ss.name', 'size' => 2],
'ico' => ['translate' => true, 'field' => 'ss.ico', 'visible' => 'N'],
'dic' => ['translate' => true, 'field' => 'ss.dic', 'visible' => 'N'],
'priceWithoutVat' => ['translate' => true, 'field' => 'total_price', 'render' => 'renderPrice'],
'dateIssued' => ['translate' => true, 'field' => 'datec', 'render' => 'renderDate'],
'dateExpiration' => ['translate' => true, 'field' => 'datee', 'render' => 'renderDate'],
'dateStockIn' => ['translate' => true, 'field' => 'datesin', 'render' => 'renderDate', 'spec' => 's.date_stock_in AS datesin'],
'code' => ['translate' => true, 'field' => 's.code'],
'payment' => ['translate' => true, 'field' => 's.payment_method'],
'closed' => ['translate' => true, 'field' => 'closed', 'size' => 0.7, 'render' => 'renderBoolean'],
'listPaid' => ['translate' => true, 'field' => 'paid', 'size' => 0.7, 'render' => 'renderBoolean'],
'note' => ['translate' => true, 'field' => 's.note'],
'currencyRate' => ['translate' => true, 'field' => 's.multiplier', 'spec' => 's.multiplier', 'render' => 'renderFloat', 'visible' => 'N'],
'foreignPrice' => ['translate' => true, 'field' => 'foreignPrice', 'visible' => 'N', 'spec' => ''],
],
];
public function &getTableDef()
{
if (!$this->tableDefLoaded) {
$tableDef = parent::getTableDef();
if (getVal('IDp')) {
$pos = array_search('priceWithoutVat', array_keys($tableDef['fields']));
$pos = intval($pos) ?: 1;
$price = ['translate' => true, 'field' => 'si.price', 'render' => 'renderPrice', 'title' => 'Cena prod.', 'visible' => 'Y', 'position' => $pos];
$priceVAT = array_merge($price, ['translate' => true, 'render' => 'renderPriceVAT', 'title' => 'Cena prod. DPH']);
$qty = ['translate' => true, 'field' => 'si.quantity', 'title' => 'Množství', 'visible' => 'Y', 'position' => $pos];
$tableDef['fields'] = array_merge(
array_slice($tableDef['fields'], 0, $pos),
['pieces' => $qty, 'listItemPrice' => $price, 'listItemPriceWithVat' => $priceVAT],
array_slice($tableDef['fields'], $pos + 1)
);
if (!empty($tableDef['fields']['foreignPrice'])) {
$tableDef['fields']['foreignPrice']['spec'] = self::getForeignPriceSpec('si.price');
}
} else {
if (!empty($tableDef['fields']['foreignPrice'])) {
$tableDef['fields']['foreignPrice']['spec'] = self::getForeignPriceSpec();
}
}
$this->tableDef = $tableDef;
}
return $this->tableDef;
}
public function customizeTableDef($tableDef)
{
if (getVal('index') == 'future') {
$column = [
'dateStockIn' => $tableDef['fields']['dateIssued'],
];
unset($tableDef['fields']['dateIssued']);
unset($tableDef['fields']['dateStockIn']);
$tableDef['fields'] = array_merge(
array_slice($tableDef['fields'], 0, 3),
$column,
array_slice($tableDef['fields'], 3),
);
}
if ((findModule(Modules::WAREHOUSE) || findModule(Modules::CHECK_APP)) && getVal('index') == 'future') {
$tableDef['fields']['stockInCheck'] = ['translate' => true, 'field' => 's.id', 'size' => 1, 'class' => 'right', 'render' => 'renderAutomaticStockIn'];
$tableDef['fields']['massStockIn'] = ['translate' => true, 'field' => 's.id', 'size' => 1, 'class' => 'right', 'render' => 'renderAutomaticMassStockIn'];
$this->pageDivide = 200;
}
return $tableDef;
}
public function getRowClass($values)
{
$flags = explodeFlags($values['flags']);
if (isset($flags['O'])) {
return 'row-blue';
}
return $this->getListRowValue($values, 'should_pay') ? 'row-red' : '';
}
public function renderICDIC($values)
{
$ICDIC = [$values['ico'], $values['dic']];
return implode(' / ', array_filter($ICDIC));
}
public function renderAutomaticStockIn($values)
{
$output = HTML::create('a');
$output
->attr('href', "javascript:nw('stockInCheck', '{$values['id']}')")
->tag('span')
->class('badge badge-primary')
->tag('span')
->class('glyphicon glyphicon-barcode')
->text(' Kontrola')
->end()
->end();
return $output;
}
public function renderAutomaticMassStockIn($values)
{
$output = HTML::create('input');
$output
->attr('style', 'margin-top: 0px;')
->attr('type', 'checkbox')
->attr('name', 'stockIns')
->attr('value', $values['id']);
return $output;
}
public function renderPrice($values, $column)
{
return printPrice($this->getListRowValue($values, $column['field']), ['ceil' => false]);
}
public function renderNumber($values, $column)
{
$index = $this->getListRowValue($values, 'id_index');
switch ($index) {
case 'future':
return 'Budoucí faktura';
case 'preorder':
return 'Předobjednávková faktura';
case 'closure':
return 'Uzávěrka '.$this->getListRowValue($values, 'number');
default:
return $this->getListRowValue($values, $column['field']);
}
}
private static function getForeignPriceSpec(string $field = 's.total_price'): string
{
// language=MariaDB
return "
IF(COALESCE(s.multiplier, 1) = 1,
'',
CONCAT_WS(' ',
FORMAT({$field} / s.multiplier, 2, 'cs_CZ'),
COALESCE(JSON_VALUE(s.data, '$.currency_symbol'), '€')
)
) AS foreignPrice
";
}
public function getSQLOrdering(&$var, &$orderParam)
{
parent::getSQLOrdering($var, $orderParam);
if (getVal('index') == 'future' && !getVal('order')) {
$var['orderField'] = 'date_issued';
$var['orderDir'] = 'ASC';
}
}
public function getQuery()
{
/** @var QueryBuilder $qb */
$qb = sqlQueryBuilder()
->select('s.id', 's.number', 's.id_index', 's.flags', 'ss.id as supplier_id, ss.name, ss.ico, ss.dic',
's.total_price as total_price', 's.date_issued as datec', 's.date_expiration AS datee',
's.code', 's.payment_method', 'IF(s.closed,\'Y\',\'N\') as closed', 'IF(s.paid,\'Y\',\'N\') as paid',
's.note', 's.date_expiration - INTERVAL 5 day < NOW() AND s.paid = \'N\' as should_pay')
->from('stock_in', 's')
->leftJoin('s', 'suppliers', 'ss', 's.id_supplier=ss.id');
extract($_REQUEST, EXTR_SKIP | EXTR_REFS);
// ###########
if (!empty($IDs)) {
/* (s.number=":IDs" OR s.code LIKE '%:IDs%') */
$qb->andWhere(Operator::orX(Operator::equals(['s.number' => $IDs]), Operator::like(['s.code' => '%'.$IDs.'%'])));
}
// ###########
if (!empty($IDp)) {
$qb->leftJoin('s', 'stock_in_items', 'si', 'si.id_stock_in=s.id')
->leftJoin('si', 'products', 'p', 'si.id_product=p.id');
if (!empty($IDv)) {
$qb->andWhere(Operator::equals(['si.id_variation' => $IDv]));
}
$qb->addSelect('si.price, p.vat, SUM(si.quantity) AS quantity')
->andWhere(Operator::equals(['si.id_product' => $IDp]))
->groupBy('s.id');
}
// ###########
if (isset($supplier) && $supplier != '') {
$qb->andWhere('( ss.name LIKE :supplier OR ss.ico LIKE :supplier)')
->setParameter('supplier', '%'.$supplier.'%');
unset($fields, $name);
}
// ###########
if (!empty($priceFrom) && intval($priceFrom) > 0) {
$priceFrom = str_replace(',', '.', $priceFrom);
$qb->andWhere('s.total_price >= :price_from')->setParameter('price_from', $priceFrom);
}
// ###########
if (!empty($priceTo) && intval($priceTo) > 0) {
$priceTo = str_replace(',', '.', $priceTo);
$qb->andWhere('s.total_price <= :price_to')->setParameter('price_to', $priceTo);
}
// ###########
if (!empty($dateFrom) || !empty($dateTo)) {
$type = !empty($dateType) ? $dateType : 'date_expiration';
if (!empty($dateFrom)) {
$qb->andWhere('s.'.$type.'>=:date_from')->setParameter('date_from', $this->prepareDate($dateFrom).' 00:00:00');
}
if (!empty($dateTo)) {
$qb->andWhere('s.'.$type.'<=:date_to')->setParameter('date_to', $this->prepareDate($dateTo).' 23:59:59');
}
}
// ###########
if (!empty($payment_method)) {
$qb->andWhere('s.payment_method = :payment_method')->setParameter('payment_method', $payment_method);
}
$index = getVal('index', null, 'invoice');
$qb->andWhere(Operator::equals(['s.id_index' => $index]));
if ($index == 'closure') {
/**
* @var $storeDataLoader StoreDataLoader
*/
$storeDataLoader = ServiceContainer::getService(StoreDataLoader::class);
$var['closure_now'] = $storeDataLoader->getCurrentStoreValue();
$sql = sqlQuery("SELECT total_price AS without_vat FROM stock_in WHERE id_index='closure' ORDER BY id DESC LIMIT 1");
$var['closure_last'] = sqlFetch($sql);
}
if ($index == 'closure') {
return [
'qb' => $qb,
'closure_now' => $var['closure_now'],
'closure_last' => $var['closure_last'],
];
} else {
return $qb;
}
}
public function recalcTotalPrice($id)
{
sqlQuery('UPDATE stock_in s
SET total_price=(
SELECT SUM(si.quantity*si.price)+s.transport_price-s.discount
FROM stock_in_items si
WHERE si.id_stock_in=s.id
)
WHERE s.id=:id', ['id' => $id]);
}
public function handleFinalizeYearStock()
{
$queryQuantity = 'SELECT p.id AS id_product, pv.id as id_variation, COALESCE(pv.in_store, p.in_store) AS quantity, p.title, v.vat
FROM products p
LEFT JOIN products_variations pv ON p.id=pv.id_product
LEFT JOIN vats AS v ON p.vat=v.id';
return $this->handleFinalizeYear($queryQuantity);
}
public function handleFinalizeYearInventory()
{
$queryQuantity = 'SELECT ii.id_product, ii.id_variation, SUM(ii.quantity) quantity, p.title, v.vat
FROM inventory_items ii
LEFT JOIN products p ON ii.id_product=p.id
LEFT JOIN vats AS v ON p.vat=v.id
GROUP BY ii.id_product, ii.id_variation';
return $this->handleFinalizeYear($queryQuantity);
}
public function handleFinalizeYear($queryQuantity)
{
$year = date('Y') - 1;
$yearNext = $year + 1;
sqlStartTransaction();
$qb = sqlQueryBuilder()->select('*')
->from('stock_in', 'si')
->where(Operator::equals(['id_index' => 'closure']))
->andWhere(Operator::equals(['number' => $year]))
->execute()->fetchOne();
if ($qb) {
return $this->returnError("Uzávěrku za rok {$year} nelze vytvořit, již byla vytvořena.", false);
}
$supplierId = returnSQLResult('SELECT MIN(id) FROM suppliers');
sqlQuery('INSERT INTO stock_in
(`number`, `code`, `closed`, `date_created`, `id_supplier`, `total_price`, `transport_price`, `date_expiration`, `date_issued`, `payment_method`, `paid`, `note`, `discount`, `finished`, `id_index`, `date_stock_in`)
VALUES (
:year, :code, 0, NOW( ), :supplierId, 0, 0, :date, :date, \'dobirka\', 0, :text, 0, 1, \'closure\', :date)',
['code' => "-{$year}", 'year' => $year, 'supplierId' => $supplierId, 'date' => "{$yearNext}-01-01", 'text' => "Uzávěrka roku {$year}"]);
$newId = sqlInsertId();
if (findModule(Modules::WAREHOUSE)) {
$date = "{$year}-12-31";
/** @var $storeDataLoader StoreDataLoader */
$storeDataLoader = ServiceContainer::getService(StoreDataLoader::class);
$queryQuantity = $storeDataLoader->getCurrentStoreQb($date)
->select("NULL, p.title, {$newId}, p.id as id_product, pv.id as id_variation,
ss.in_store as quantity, r.average_price as price, v.vat");
sqlQuery("INSERT INTO stock_in_items
(`id`, `name`, `id_stock_in`, `id_product`, `id_variation`, `quantity`, `price`, `vat`)
{$queryQuantity->getSQL()}", $queryQuantity->getParameters());
} else {
sqlQuery("INSERT INTO stock_in_items
(`id`, `name`, `id_stock_in`, `id_product`, `id_variation`, `quantity`, `price`, `vat`)
SELECT NULL, i.title, {$newId}, i.id_product, i.id_variation, quantity, average_price, i.vat
FROM
(
{$queryQuantity}
) i
LEFT JOIN
(
SELECT sii.id_product, sii.id_variation, SUM(sii.quantity*sii.price)/SUM(sii.quantity) average_price
FROM stock_in_items sii
LEFT JOIN stock_in si ON si.id=sii.id_stock_in
WHERE COALESCE(si.date_stock_in, si.date_issued) >= '{$year}-01-01' AND COALESCE(si.date_stock_in, si.date_issued) < '{$yearNext}-01-01'
AND (si.id_index != 'future') AND (sii.quantity > 0)
GROUP BY sii.id_product, sii.id_variation
) s ON i.id_product = s.id_product AND (i.id_variation IS NULL OR i.id_variation = s.id_variation)
WHERE quantity > 0");
}
$this->recalcTotalPrice($newId);
sqlQuery("UPDATE stock_in SET closed = 1 WHERE date_stock_in < '{$yearNext}-01-01'");
sqlFinishTransaction();
return $this->returnOK("Byla vytvořena uzávěrka za rok {$year}", false, ['index' => 'closure']);
}
public function handleExportCurrentStore()
{
$date = getVal('date');
$filename = 'uzaverka-'.date('Y-m-d', strtotime($date ?? 'today')).'.xlsx';
ini_set('memory_limit', '512M');
ini_set('max_execution_time', '180');
/** @var ExcelGenerator $excelGenerator */
$excelGenerator = ServiceContainer::getService(ExcelGenerator::class);
$header = (new ExcelHeaderBuilder())
->int('ID produktu', 'id_product')
->int('ID varianty', 'id_variation')
->string('EAN', 'ean')
->string('Kod', 'code')
->string('Produkt', 'product_title')
->string('Varianta', 'variation_title')
->price('Vážená nákupní cena bez DPH', 'average_price')
->float('Počet kusů', 'in_store')
->price('Hodnota zboží na skladě', 'warehouse_value')
->int('DPH', 'vat')
->price('Nákupní cena bez DPH', 'price_buy');
$data = function () use ($date) {
/**
* @var $storeDataLoader StoreDataLoader
*/
$storeDataLoader = ServiceContainer::getService(StoreDataLoader::class);
$sql = $storeDataLoader->getCurrentStoreQb($date)
->select(
'COALESCE(pv.ean, p.ean) as ean, p.id as id_product, pv.id as id_variation,
p.title as product_title, pv.title as variation_title, v.vat, COALESCE(pv.code, p.code) as code,
r.average_price, COALESCE(pv.price_buy, p.price_buy) as price_buy'
);
$in_store_source = findModule(Modules::WAREHOUSE) ? 'ss' : 's';
$sql->addSelect("{$in_store_source}.in_store, ({$in_store_source}.in_store * r.average_price) as warehouse_value");
$sum = 0;
foreach ($sql->execute() as $row) {
$sum += $row['warehouse_value'];
yield $row;
}
yield [
'ean' => 'Celkem',
'id_product' => null,
'id_variation' => null,
'product_title' => null,
'variation_title' => null,
'vat' => null,
'code' => null,
'average_price' => null,
'price_buy' => null,
'in_store' => null,
'warehouse_value' => $sum,
];
};
$excelGenerator->generateExcel($header->getHeader(), $header->formatData($data()), $filename);
writeDownActivity('Export hodnoty skladu');
exit;
}
public function handleStockInExport()
{
$header = [
['name' => 'Číslo faktury'],
['name' => 'Datum', 'type' => 'datetime', 'format' => 'd.m.yyyy'],
['name' => 'Produkt'],
['name' => 'Varianta'],
['name' => 'Kód'],
['name' => 'Kód u dodavatele'],
['name' => 'EAN', 'type' => DataType::TYPE_STRING],
['name' => 'Množství', 'type' => DataType::TYPE_NUMERIC],
['name' => 'Dodavatel'],
['name' => 'Nák. cena v měně/ks', 'type' => DataType::TYPE_NUMERIC],
['name' => 'Měna'],
['name' => 'Nák. cena/ks v CZK', 'type' => DataType::TYPE_NUMERIC],
['name' => 'Celk. cena v měně', 'type' => DataType::TYPE_NUMERIC],
['name' => 'Měna'],
['name' => 'Kurz', 'type' => DataType::TYPE_NUMERIC],
['name' => 'Aktuálně skladem', 'type' => DataType::TYPE_NUMERIC],
['name' => 'Prodejní cena', 'type' => DataType::TYPE_NUMERIC, 'format' => '0.00'],
['name' => 'Aktuální nák. cena', 'type' => DataType::TYPE_NUMERIC],
];
if (findModule(Modules::STORES)) {
$header[] = ['name' => 'Sklad'];
}
/** @var ExcelGenerator $excelGenerator */
$excelGenerator = ServiceContainer::getService(ExcelGenerator::class);
$now = (new DateTime())->format('d-m-Y_H-i-s');
$excelGenerator->generateExcel($header, $this->getExportData(), "export-naskladneni-{$now}.xlsx");
exit;
}
protected function getExportData()
{
$qb = $this->getQuery()
->select("s.code as invoice_number, s.date_issued, p.title product_title, pv.title variation_title, COALESCE(pv.code, p.code) as code, ps.code as code_supplier, COALESCE(pv.ean, p.ean), si.quantity as quantity, ss.name as supplier_name,
si.price/s.multiplier as price, JSON_UNQUOTE(json_extract(s.data, '$.currency_symbol')) as symbol, si.price as price_czk, (si.price/s.multiplier)*si.quantity as price_sum, JSON_UNQUOTE(json_extract(s.data, '$.currency_symbol')) as price_sum_symbol, s.multiplier as rate,
coalesce(pv.in_store, p.in_store) as in_store, coalesce(pv.price, p.price)*(1+(v.vat/100)) as unit_price
")
->innerJoin('s', 'stock_in_items', 'si', 's.id=si.id_stock_in')
->innerJoin('si', 'products', 'p', 'si.id_product=p.id')
->leftJoin('si', 'products_variations', 'pv', 'si.id_variation=pv.id')
->leftJoin('si', 'products_of_suppliers', 'ps', 'si.id_product=ps.id_product
and si.id_variation=ps.id_variation and s.id_supplier=ps.id_supplier')
->innerJoin('p', 'vats', 'v', 'p.vat=v.id')
;
if (findModule(Modules::PRODUCTS, Modules::SUB_PRICE_BUY)) {
$qb->addSelect('coalesce(pv.price_buy, p.price_buy) as price_buy');
}
if (findModule(Modules::STORES)) {
$qb->addSelect('st.name as store')->leftJoin('s', 'stores', 'st', "st.id=JSON_UNQUOTE(JSON_EXTRACT(s.data, '$.id_store'))");
}
foreach ($qb->execute() as $values) {
yield array_values($values);
}
}
}

View File

@@ -0,0 +1,39 @@
<?php
use KupShop\AdminBundle\AdminList\BaseList;
use KupShop\CatalogBundle\Query\Search;
class SuppliersList extends BaseList
{
protected $tableName = 'suppliers';
protected ?string $tableAlias = 's';
protected $showMassEdit = true;
protected $tableDef = [
'id' => 's.id',
'fields' => [
'name' => ['translate' => true, 'field' => 's.name'],
'ico' => ['translate' => true, 'field' => 's.ico', 'spec' => 's.ico', 'fieldType' => BaseList::TYPE_STRING],
'dic' => ['translate' => true, 'field' => 's.dic', 'spec' => 's.dic', 'visible' => 'N', 'fieldType' => BaseList::TYPE_STRING],
'phone' => ['translate' => true, 'field' => 's.phone', 'spec' => 's.phone', 'visible' => 'N', 'fieldType' => BaseList::TYPE_STRING],
'address' => ['translate' => true, 'field' => 's.address', 'spec' => 's.address', 'fieldType' => BaseList::TYPE_STRING],
'email' => ['translate' => true, 'field' => 's.email', 'spec' => 's.email', 'fieldType' => BaseList::TYPE_STRING],
],
];
public function getQuery()
{
$qb = sqlQueryBuilder()->select('s.id, s.name')->from('suppliers', 's');
if ($value = getVal('value')) {
$qb->andWhere(Search::searchFields($value, [
['field' => 's.name', 'match' => 'both'],
['field' => 's.ico', 'match' => 'both'],
['field' => 's.email', 'match' => 'both'],
['field' => 's.phone', 'match' => 'both'],
]));
}
return $qb;
}
}

View File

@@ -0,0 +1,57 @@
<?php
use KupShop\AdminBundle\AdminList\BaseList;
/**
* Created by PhpStorm.
* User: hanz
* Date: 12.6.14
* Time: 14:46.
*/
class TemplatesCategoriesList extends BaseList
{
use AdminListSortable;
protected $template = 'listSortable.tpl';
protected $showMassEdit = true;
protected $tableName = 'templates_categories';
protected ?string $tableAlias = 'tc';
protected $tableDef = [
'id' => 'tc.id',
'fields' => [
'position' => ['translate' => true, 'field' => 'tc.position', 'render' => 'renderPosition', 'size' => '70px'],
'name' => ['translate' => true, 'field' => 'tc.name', 'spec' => 'tc.name', 'fieldType' => BaseList::TYPE_STRING],
],
];
public function getSQLOrdering(&$var, &$orderParam)
{
parent::getSQLOrdering($var, $orderParam);
$var['orderField'] = 'position';
}
public function handle()
{
parent::handle();
$item = getVal('moved_item');
if (!empty($item)) {
$this->saveList($item, 'templates_categories');
exit('{}');
}
}
public function getQuery()
{
$qb = sqlQueryBuilder();
$qb->select('id', 'position')
->from(getTableName('templates_categories'), 'tc')
->where(1);
return $qb;
}
}

View File

@@ -0,0 +1,88 @@
<?php
use KupShop\AdminBundle\AdminList\BaseList;
use KupShop\I18nBundle\Admin\Util\ListTranslationsFigureBadges;
class TemplatesList extends BaseList
{
use AdminListSortable;
use ListTranslationsFigureBadges;
protected $template = 'listSortable.tpl';
protected $showMassEdit = true;
protected $tableName = 'templates';
protected ?string $tableAlias = 't';
protected $orderParam = [
'sort' => 'Šablona',
'direction' => 'DESC',
];
protected $tableDef = [
'id' => 't.id',
'fields' => [
'template' => ['translate' => true, 'field' => 't.name', 'spec' => 'CONCAT_WS(" - ", tc.name, t.name) name', 'fieldType' => BaseList::TYPE_STRING],
// 'Text' => ['field'=>'text', 'renderer'=>'renderHTML'],
'visible' => ['translate' => true, 'render' => 'renderBoolean', 'field' => 't.figure', 'spec' => 't.figure', 'fieldType' => BaseList::TYPE_BOOL],
],
];
public function getQuery()
{
$qb = sqlQueryBuilder()
->select('t.id', 't.position as position')
->from(getTableName('templates'), 't')
->leftJoin('t', getTableName('templates_categories'), 'tc', 't.id_category = tc.id')
->where(1);
if ($name = getVal('name')) {
$qb->andWhere('t.name LIKE :name OR tc.name LIKE :name ')->setParameter('name', '%'.$name.'%');
}
if (getVal('id_category') != null) {
$qb->andWhere(\Query\Operator::equals(['t.id_category' => getVal('id_category')]));
}
return $qb;
}
public function customizeTableDef($tableDef)
{
$tableDef = parent::customizeTableDef($tableDef);
if (getVal('sortable') == true) {
$tableDef['fields'] =
array_merge(['Pořadí' => ['field' => 'position', 'render' => 'renderPosition', 'size' => '70px']], $this->tableDef['fields']);
$this->orderParam = [
'sort' => 'Pořadí',
'direction' => 'ASC',
];
$this->pageDivide = 1000;
}
if (findModule(\Modules::TRANSLATIONS)) {
$tableDef['fields']['translationsFigure'] = $this->getTranslationsFigureField(
translationClass: \KupShop\I18nBundle\Translations\TemplatesTranslation::class,
column: ['translation_section' => 'translations'],
);
}
return $tableDef;
}
public function handle()
{
parent::handle();
$item = getVal('moved_item');
if (!empty($item)) {
$parts = parse_url(getVal('url'));
parse_str($parts['query'], $query);
$idCategory = $query['id_category'] ?? '';
$this->saveList($item, 'templates', extra_where: empty($idCategory) ? '' : " AND id_category = {$idCategory}");
exit('{}');
}
}
}

View File

@@ -0,0 +1,33 @@
<?php
use KupShop\AdminBundle\AdminList\BaseList;
/**
* Created by PhpStorm.
* User: hanz
* Date: 3.6.14
* Time: 12:30.
*/
class UsersGroupsList extends BaseList
{
use AdminListSortable;
protected $showMassEdit = true;
protected $tableName = 'users_groups';
protected ?string $tableAlias = 'ug';
protected $tableDef = [
'id' => 'id',
'fields' => [
'name' => ['translate' => true, 'field' => 'ug.name', 'spec' => 'ug.name', 'fieldType' => BaseList::TYPE_STRING],
'description' => ['translate' => true, 'field' => 'ug.descr', 'spec' => 'ug.descr', 'render' => 'renderHTML', 'fieldType' => BaseList::TYPE_STRING],
'users_in_group' => ['translate' => true, 'field' => 'count'],
],
];
public function getQuery()
{
$qb = sqlQueryBuilder()->select('id', '(SELECT COUNT(ugr.id_user) FROM `users_groups_relations` as ugr WHERE ugr.id_group=ug.id) as count')->from('users_groups', 'ug');
return $qb;
}
}

View File

@@ -0,0 +1,3 @@
<?php
class_alias('KupShop\UserBundle\Admin\lists\UsersList', 'Admin\Lists\UsersList');

59
admin/lists/VatsList.php Normal file
View File

@@ -0,0 +1,59 @@
<?php
use KupShop\AdminBundle\AdminList\BaseList;
use KupShop\AdminBundle\Query\Invert;
class VatsList extends BaseList
{
protected $tableDef = [
'id' => 'id',
'fields' => [
'Popis DPH' => ['field' => 'descr'],
'Procento' => ['field' => 'vat'],
'Priorita' => ['field' => 'is_default', 'render' => 'renderDefault'],
],
];
public function customizeTableDef($tableDef)
{
$tableDef = parent::customizeTableDef($tableDef);
if (findModule(Modules::OSS_VATS)) {
$tableDef['fields']['Země'] = ['field' => 'name'];
$this->orderParam = [
'sort' => 'Země',
'direction' => 'ASC',
];
}
return $tableDef;
}
public function renderDefault($values, $column)
{
$value = $this->getListRowValue($values, $column['field']);
return ($value == 'Y') ? 'Hlavní' : '';
}
public function getQuery()
{
$qb = sqlQueryBuilder()->select('v.id, v.descr, v.vat, v.is_default')->from('vats', 'v');
if (findModule(Modules::OSS_VATS)) {
$qb->leftJoin('v', 'countries', 'c', 'c.id = v.id_country')->addSelect('c.name');
$countries = getVal('country', $_GET);
$countries_invert = getVal('country_invert', $_GET);
if (!empty($countries)) {
$qb->andWhere(Invert::checkInvert(\Query\Operator::inStringArray($countries, 'id_country'), isset($countries_invert)));
}
if ($automanaged = getVal('automanaged')) {
$qb->andWhere(\Query\Operator::inIntArray($automanaged, 'v.automanaged'));
}
}
return $qb;
}
}