Archives
Trending
Support
Login
clear text
XML
Django
JavaScript
MATLAB
C
C++
C#
Python
SQL
Shell
Bash
Markdown
YAML
JSON
HTML
CSS
PHP
Java
Ruby
Go
Rust
Swift
Kotlin
Arduino
TypeScript
Perl
Autohotkey
Lua
SQF
R
Scala
Haskell
Groovy
Dart
Clojure
VB.NET
Objective-C
PowerShell
Bash
CoffeeScript
Verilog
controller) { $context->controller = new FrontController(); $context->controller->init(); } } // Гарантиране на shop контекст if (Shop::isFeatureActive()) { if (!Shop::getContext()) { Shop::setContext(Shop::CONTEXT_SHOP, (int)Configuration::get('PS_SHOP_DEFAULT')); } } } catch (Exception $e) { http_response_code(500); header('Content-Type: application/json; charset=utf-8'); echo json_encode(array('error' => 'PrestaShop initialization failed: ' . $e->getMessage())); exit; } // ---------- ГАРАНТИРАН КОНТЕКСТ ---------- $context = Context::getContext(); // Shop if (!$context->shop || !(int)$context->shop->id) { $idShop = (int)Configuration::get('PS_SHOP_DEFAULT'); if ($idShop) { $context->shop = new Shop($idShop); Shop::setContext(Shop::CONTEXT_SHOP, $idShop); } } // Language if (!$context->language || !(int)$context->language->id) { $idLang = (int)Configuration::get('PS_LANG_DEFAULT'); if ($idLang) $context->language = new Language($idLang); } // Currency if (!$context->currency || !(int)$context->currency->id) { $idCur = (int)Configuration::get('PS_CURRENCY_DEFAULT'); if ($idCur) $context->currency = new Currency($idCur); } // Country if (!$context->country || !(int)$context->country->id) { $idCountry = (int)Configuration::get('PS_COUNTRY_DEFAULT'); if ($idCountry) $context->country = new Country($idCountry); } $link = $context->link; // ---------- ПОМОЩНИ ФУНКЦИИ ---------- function ps_get_active_languages() { static $langs = null; if ($langs === null) { $langs = Language::getLanguages(true, Context::getContext()->shop->id); } return $langs; } function ps_currency() { static $cur = null; if ($cur === null) { $defaultId = (int)Configuration::get('PS_CURRENCY_DEFAULT'); $cur = new Currency($defaultId); } return $cur; } // Активни продукти (ID desc) function ps_fetch_active_products($offset=0, $limit=100000) { $sql = (new DbQuery()) ->select('p.id_product, p.reference') ->from('product', 'p') ->innerJoin('product_shop', 'ps', 'p.id_product = ps.id_product AND ps.id_shop = '.(int)Context::getContext()->shop->id) ->where('ps.active = 1') ->orderBy('p.id_product DESC') ->limit((int)$limit, (int)$offset); $rows = Db::getInstance()->executeS($sql); return $rows ? $rows : array(); } // Имена и link_rewrite за всички активни езици function ps_fetch_names_for_product($id_product) { $langs = ps_get_active_languages(); $ids = array(); foreach ($langs as $l) $ids[] = (int)$l['id_lang']; if (!$ids) return array(); $sql = (new DbQuery()) ->select('pl.id_lang, pl.name, pl.link_rewrite') ->from('product_lang', 'pl') ->where('pl.id_product='.(int)$id_product) ->where('pl.id_shop='.(int)Context::getContext()->shop->id) ->where('pl.id_lang IN ('.implode(',', $ids).')'); $rows = Db::getInstance()->executeS($sql); $out = array(); if ($rows) { foreach ($rows as $r) { $out[(int)$r['id_lang']] = array( 'name' => $r['name'], 'link_rewrite' => $r['link_rewrite'], ); } } return $out; } // id на кавър изображението function ps_cover_image_id($id_product) { $cover = Image::getCover($id_product); if ($cover && !empty($cover['id_image'])) return (int)$cover['id_image']; return null; } // URL за миниатюра + URL към продукта function ps_image_and_product_links($id_product, $namesByLang, $link) { $langs = ps_get_active_languages(); $firstLangId = (int)$langs[0]['id_lang']; $linkRewrite = isset($namesByLang[$firstLangId]['link_rewrite']) ? $namesByLang[$firstLangId]['link_rewrite'] : 'product'; $coverId = ps_cover_image_id($id_product); // Определяне на типа изображение $thumbType = 'home_default'; if (class_exists('ImageType')) { if (method_exists('ImageType','getFormattedName')) { $thumbType = ImageType::getFormattedName('home'); } elseif (method_exists('ImageType','getFormatedName')) { $thumbType = ImageType::getFormatedName('home'); } } $imgUrl = $coverId ? $link->getImageLink($linkRewrite, $coverId, $thumbType) : null; $productUrl = $link->getProductLink($id_product, $linkRewrite, null, null, $firstLangId); return array($imgUrl, $productUrl); } // Наличности по комбинации function ps_sizes_and_qty($id_product) { $langs = ps_get_active_languages(); $id_lang = (int)$langs[0]['id_lang']; $prod = new Product($id_product, false, $id_lang, Context::getContext()->shop->id); $combs = $prod->getAttributeCombinations($id_lang); if (!$combs) $combs = array(); $byAttr = array(); foreach ($combs as $c) { $ipa = (int)$c['id_product_attribute']; if (!isset($byAttr[$ipa])) $byAttr[$ipa] = array('attrs'=>array(), 'ipa'=>$ipa); $gname = isset($c['group_name']) ? mb_strtolower($c['group_name']) : ''; $aname = isset($c['attribute_name']) ? $c['attribute_name'] : ''; $byAttr[$ipa]['attrs'][] = array('group'=>$gname, 'name'=>$aname); } $preferSize = array(); foreach ($byAttr as $ipa => $data) { foreach ($data['attrs'] as $a) { if (preg_match('/(size|размер)/iu', $a['group'])) { $preferSize[$ipa] = true; break; } } } $rows = array(); foreach ($byAttr as $ipa => $data) { $qty = (int)StockAvailable::getQuantityAvailableByProduct($id_product, $ipa, (int)Context::getContext()->shop->id); $sizeLabel = null; if (!empty($preferSize[$ipa])) { foreach ($data['attrs'] as $a) { if (preg_match('/(size|размер)/iu', $a['group'])) { $sizeLabel = $a['name']; break; } } } if ($sizeLabel === null) { $parts = array(); foreach ($data['attrs'] as $a) { $parts[] = $a['name']; } $sizeLabel = implode(' / ', $parts); } $rows[] = array('label'=>$sizeLabel, 'qty'=>$qty); } $withStock = array(); foreach ($rows as $r) { if ($r['qty'] > 0) $withStock[] = $r; } return $withStock ? $withStock : $rows; } // Общо наличност function ps_total_qty($id_product) { return (int)StockAvailable::getQuantityAvailableByProduct($id_product, 0, (int)Context::getContext()->shop->id); } // Цени function ps_prices($id_product) { $ctx = Context::getContext(); $idShop = (int)$ctx->shop->id; $idCur = (int)$ctx->currency->id; // Базова цена от product_shop $q = new DbQuery(); $q->select('ps.price') ->from('product_shop', 'ps') ->where('ps.id_product='.(int)$id_product) ->where('ps.id_shop='.(int)$idShop); $row = Db::getInstance()->getRow($q); $base = $row ? (float)$row['price'] : 0.0; // Търсене на специфични цени $now = date('Y-m-d H:i:s'); $spQ = new DbQuery(); $spQ->select('reduction, reduction_type') ->from('specific_price', 'sp') ->where('sp.id_product='.(int)$id_product) ->where('sp.id_shop IN (0,'.(int)$idShop.')') ->where('sp.id_currency IN (0,'.(int)$idCur.')') ->where('sp.id_country IN (0,'.(int)$ctx->country->id.')') ->where('sp.id_group = 0') ->where('sp.id_customer = 0') ->where('(sp.from = "0000-00-00 00:00:00" OR sp.from <= "'.$now.'")') ->where('(sp.to = "0000-00-00 00:00:00" OR sp.to >= "'.$now.'")') ->orderBy('sp.id_specific_price DESC'); $sp = Db::getInstance()->getRow($spQ); $current = $base; if ($sp && (float)$sp['reduction'] > 0) { if ($sp['reduction_type'] === 'percentage') { $current = $base * (1.0 - (float)$sp['reduction']); } else { // amount $current = $base - (float)$sp['reduction']; } if ($current < 0) $current = 0.0; } // ДОБАВЕТЕ ТУК УМНОЖЕНИЕТО С 1.2 ЗА ДДС $base_with_vat = $base * 1.2; $current_with_vat = $current * 1.2; return array((float)$base, (float)$current); } // Форматиране на цена function ps_fmt_price($price) { // Добавяне на ДДС $price_with_vat = $price * 1.2; return Tools::displayPrice($price, ps_currency()); } // Събиране на данните function ps_collect_data() { $products = ps_fetch_active_products(0, 100000); $langs = ps_get_active_languages(); $out = array(); foreach ($products as $p) { $id = (int)$p['id_product']; $ref = $p['reference']; $names = ps_fetch_names_for_product($id); list($imgUrl, $pUrl) = ps_image_and_product_links($id, $names, Context::getContext()->link); // Имена за всички активни езици $nameParts = array(); foreach ($langs as $l) { $id_lang = (int)$l['id_lang']; $iso = $l['iso_code']; $nm = isset($names[$id_lang]['name']) ? $names[$id_lang]['name'] : ''; if ($nm !== '') { $nameParts[] = '
['.$iso.'] '.$nm.'
'; } } $namesAll = implode("\n", $nameParts); // Размери + количества $sizes = ps_sizes_and_qty($id); $sizeParts = array(); foreach ($sizes as $s) { $label = isset($s['label']) ? $s['label'] : ''; $qty = isset($s['qty']) ? (int)$s['qty'] : 0; $sizeParts[] = $label . ': ' . $qty; } $sizesStr = implode("\n", $sizeParts); $totalQty = ps_total_qty($id); list($base, $curr) = ps_prices($id); // ДОБАВЕТЕ ДДС ТУК ДИРЕКТНО $base_with_vat = $base * 1.2; $curr_with_vat = $curr * 1.2; $out[] = array( 'id' => $id, 'reference' => $ref, 'image' => $imgUrl, 'plink' => $pUrl, 'names' => $namesAll, 'sizes' => $sizesStr, 'total' => $totalQty, 'base' => ps_fmt_price($base * 1.2), //Това умножение по 1,2 се прави за да показва цената с ДДС 'current' => ps_fmt_price($curr * 1.2), //Това умножение по 1,2 се прави за да показва цената с ДДС 'has_disc' => ($curr < $base) ? 1 : 0, //'disc_percent' => ($base > 0 && $curr < $base) ? (int)round((($base - $curr) / $base) * 100) : 0, 'disc_percent' => ($base > 0 && $curr < $base) ? (int) round((($base - $curr) / $base) * 100) : 0, ); } return $out; } // ---------- РЕЖИМИ (AJAX/EXPORT/VIEW) ---------- if (isset($_GET['action']) && $_GET['action'] === 'data') { header('Content-Type: application/json; charset=utf-8'); try { $data = ps_collect_data(); echo json_encode(array('data'=>$data), JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); } catch (Exception $e) { echo json_encode(array('error'=>'Грешка при събиране на данни: ' . $e->getMessage())); } exit; } // Експорт към Excel (CSV UTF-8 BOM) if (isset($_GET['export']) && $_GET['export'] === '1') { try { $rows = ps_collect_data(); $filename = 'products_export_' . date('Ymd_His') . '.csv'; header('Content-Type: text/csv; charset=utf-8'); header('Content-Disposition: attachment; filename="' . $filename . '"'); echo "\xEF\xBB\xBF"; $out = fopen('php://output', 'w'); fputcsv($out, array( 'ID','Reference','Product URL','Image URL','Names (all languages)', 'Sizes (qty)','Total Qty','Base Price','Current Price','Discount %', ), ';'); foreach ($rows as $r) { fputcsv($out, array( $r['id'], $r['reference'], $r['plink'], $r['image'], preg_replace("/\r?\n/", ' | ', $r['names']), preg_replace("/\r?\n/", ' | ', $r['sizes']), $r['total'], $r['base'], $r['current'], ($r['disc_percent'] > 0 ? ('-' . $r['disc_percent'] . '%') : ''), ), ';'); } fclose($out); } catch (Exception $e) { header('Content-Type: text/plain; charset=utf-8'); echo 'Грешка при експорт: ' . $e->getMessage(); } exit; } ?>
Активни продукти – репорт
Активни продукти /
Неактивни с наличност за продажба!
📊 Експорт в Excel (CSV)
Зареждане на данни…
Може да отнеме малко време при много продукти.
ID
Ref
Снимка
Име (всички езици)
Размери (наличности)
Общо наличност
Цена (с ДДС)
Mark as private (unlisted)
for 30 minutes
for 6 hours
for 1 day
for 1 week
for 1 month
for 1 year
everlasting (like CCCP)