Перейти к содержимому


Штатные ошибки ShopCMS, из коробки :).


  • Вы не можете ответить в тему
Сообщений в теме: 42

#1 badisoft

    Продвинутый пользователь

  • Assistent vsupport.club
  • PipPipPip
  • 5075 сообщений
Репутация: 786
Мастер

Отправлено 09 November 2014 - 03:57 PM

Решил собрать в кучу и худо-бедно причесать найденные в ShopCMS штатные ошибки и странности:

================================================
Штатная ошибка. Из-за нее незарегистрированный пользователь не сможет скачать купленный им электронный товар.

В файле core/includes/processor/get_file.php
строку:


$q = db_query("select order_time from ".ORDERS_TABLE." where orderID=".orderID);


нужно заменить на:


$q = db_query("select order_time from ".ORDERS_TABLE." where orderID=".$orderID);


P.S. Чтобы незарегистрированный пользователь мог получить ссылку на электронный товар, нужно в общих настройках админ-панели поставить галочку напротив пункта E-mail отчеты для покупателей

=====================

Нашел ошибку в catalog_extra.php (штатную). Перепутаны таблицы, это вызывает ошибку SQL при удалении варианта характеристики.
Исправление:


#db_query("delete from ".CATEGORY_PRODUCT_OPTIONS_TABLE." where variantID=".$variantid);
db_query("delete from ".CATEGORY_PRODUCT_OPTION_VARIANTS." where variantID=".$variantid);


=============================

Штатная ошибка: При импорте из CSV варианты характеристик, содержащие символы '"<>& двоятся, т.е. создаются столько раз, сколько товаров с таким вариантом характеристики.

Исправление: в функции optOptionValueExists строку


" where optionID=".(int)$optionID." and option_value='".xEscSQL(trim($value_name))."';");


заменяем на


#" where optionID=".(int)$optionID." and option_value='".xEscSQL(trim($value_name))."';");
" where optionID=".(int)$optionID." and option_value='".xToText(trim($value_name))."';");



=============================

Есть в discount_functions.php функция _calculateGeneralPriceDiscount, возвращающая размер скидки в зависимости от суммы заказа. Выглядит она вот так:


function _calculateGeneralPriceDiscount( $orderPrice, $log )
{
$customerID = (int)regGetIdByLogin($log);
$q = db_query("select discount_id, price_range, percent_discount from ".
ORDER_PRICE_DISCOUNT_TABLE." order by price_range " );
$data = array();
while( $row = db_fetch_row($q) ) $data[] = $row;

if ( count($data) != 0 )
{
for( $i=0; $i<count($data)-1; $i++ )
{
if ( $data[$i][ "price_range" ] < $orderPrice
&& $orderPrice < $data[$i+1][ "price_range" ] )
return $data[$i][ "percent_discount" ];
}
if ( $data[ count($data)-1 ][ "price_range" ] < $orderPrice )
return $data[ count($data)-1 ][ "percent_discount" ];
}

return 0;
}


Если сумма заказа совпадает с суммой, от которой начинается новая скидка, то скидка будет ноль :).
Т.е. если до 5000руб скидка 4%, а от 5000руб - 5%, то на заказ 4999руб будет скидка 4%, на 5001руб - 5%, а вот на 5000руб - 0% :))).

В общем, зачем там такой развесистый код я не понял и заменил на:


function _calculateGeneralPriceDiscount( $orderPrice, $log )
{
$data = db_query("SELECT price_range, percent_discount FROM ".ORDER_PRICE_DISCOUNT_TABLE." ORDER BY price_range");
$discount = 0;
while( $row = db_fetch_row($data) ) if ($row['price_range'] <= $orderPrice) $discount = $row['percent_discount'];
return $discount;
}


===========================

Нашел не ошибку, но весьма странный стиль программирования.
файл cart_functions.php, функция cartGetCartContent()


$costUC = GetPriceProductWithOption( $variants, $shopping_cart_item["productID"] );
$tmp = array(
"productID" => $product["productID"],
...
"costUC" => $costUC,
"cost" => show_price($cart_item["Quantity"]*GetPriceProductWithOption($variants,$shopping_cart_item["productID"])),
...


Зачем вычислять второй раз GetPriceProductWithOption($variants,$shopping_cart_item["productID"]), когда ровно это же число находится в переменной $costUC строкой выше? Оно ведь нифига не бесплатно:


function GetPriceProductWithOption($variants, $productID)
{
$q=db_query("select Price from ".PRODUCTS_TABLE." where productID=".(int)$productID);
$r=db_fetch_row($q);
$base_price = (float)$r[0];
$full_price = (float)$base_price;
foreach($variants as $vars)
{
$q1=db_query("select price_surplus from ".PRODUCTS_OPTIONS_SET_TABLE.
" where productID=".(int)$productID." AND variantID=".(int)$vars);
$r1=db_fetch_row($q1);
$full_price += $r1["price_surplus"];
}
return $full_price;
}


т.е. при десяти возможных вариантах получаем лишних 11 SQL-запросов.

А если посмотреть, то и вообще всю функцию GetPriceProductWithOption можно заменить на "двухзапросную". Первым запросом получаем базовую цену, вторым - изменение от базовой для переданного набора вариантов.


function GetPriceProductWithOption($variants, $productID)
{
$row=db_fetch_assoc(db_query("SELECT Price FROM ".PRODUCTS_TABLE." WHERE productID=$productID LIMIT 1"));
if (!$variants) return $row['Price'];
$row1=db_fetch_assoc(db_query("SELECT SUM(price_surplus) AS price_surplus FROM ".PRODUCTS_OPTIONS_SET_TABLE." WHERE productID=$productID AND variantID IN (".implode(',',$variants).")"));
return $row['Price']+$row1['price_surplus'];
}




=================================

На этот раз ошибка ни на что не влияющая, но прикольная :).
файл product_functions.php
функция GetExtraParametrs
в SQL-запросе чудный текст (два раза повторяется одно условие):


WHERE povvt.optionID='.$_Row['optionID'].' AND post.productID='.$_Row['productID'].' AND povvt.optionID='.$_Row['optionID']


==================================

Ошибка: штатный и аж четыре раза встречающийся в index.php код совершенно бессмысленен:


if ($smarty -> get_template_vars("main_content_template") == ("category.tpl.html" || "category_search_result.tpl.html"))


Это кусок условия вывода блоков. Левого, правого, верхнего, нижнего. Четыре одинаковых куска кода.

Правильно так:


if ($smarty -> get_template_vars("main_content_template") == "category.tpl.html" || get_template_vars("main_content_template") == "category_search_result.tpl.html")


==================================

Не ошибка. Просто заменяем многострочное извращение с ob_start() на var_export(), появившийся в PHP5
Снимает проблему "белого экрана" в некоторых редких случаях.


function db_query($s) //database query

[...]

/*
ob_start();
var_dump($_GET);
var_dump($_POST);
$tmpa=ob_get_contents();
ob_end_clean();
$out .= $tmpa;
*/
$out .= var_export($_REQUEST,true);


====================================

Аналогично.


function error_reporting_log($error_num, $error_var, $error_file, $error_line) {

[...]

/*
ob_start();
var_dump($_GET);
var_dump($_POST);
$tmpa = ob_get_contents();
ob_end_clean();
$out .= $tmpa;
*/
$out .= var_export($_REQUEST,true);


========================================

Если разрешено задавать количество товара при добавлении в корзину (опция "Разрешить указывать количество товара для добавления в корзину"), а у товара задана не единица в минимальном заказе (скажем, купить можно начиная от N штук), то при задании в окошке выбранного количества числа M получим в корзине не М товаров, а M+N-1. Происходит это потому, что товар добавляется поштучно в цикле от 1 до M (см. shopping_cart.php)


for ($mcn=0; $mcn<$_GET["multyaddcount"]; $mcn++) cartAddToCart( $_GET["add2cart"], $variants );


но при каждом "поштучном" добавлении происходит проверка корзины и если товара там еще нет (первое добавление), то добавляется не 1, а N (см. cart_functions.php, cartAddToCart)


$count_to_order = 1;
....
if ( $item_index == -1 ) $count_to_order = $min_order_amount;
....
db_query("UPDATE ".SHOPPING_CARTS_TABLE." SET Quantity=".(int)$count_to_order....


Решение:

1. в файле cart_functions.php в функции cartAddToCart заменяем


return true;


на


return $count_to_order;


все равно нигде (ни в одном месте из двух :)) не проверяется, что вернула эта функция.

2. в файле cart.php находим строку cartAddToCart

и заменяем


for ( $mcn = 0; $mcn < $_GET["multyaddcount"]; $mcn++ )
cartAddToCart(( int ) $_GET["addproduct"], $variants);


на


for ( $mcn = 0; $mcn < $_GET["multyaddcount"]; $mcn+=$added )
if (!$added = cartAddToCart(( int ) $_GET["addproduct"], $variants)) break;


3. в файле shopping_cart.php находим строку cartAddToCart

и заменяем


for ($mcn=0; $mcn<$_GET["multyaddcount"]; $mcn++) cartAddToCart( $_GET["add2cart"], $variants );


на


for ($mcn=0; $mcn<$_GET["multyaddcount"]; $mcn+=$added) if (!$added = cartAddToCart( $_GET["add2cart"], $variants )) break;


============================================

В модулях курьерской доставки (файлы class.courier2.php и class.courier.php) SQL-таблица SS__courier_rates не имеет префикса, т.е. при двух и более сайтах в одной SQL-базе могут быть проблемы,
т.к. при удалении этого модуля доставки таблица чистится либо удаляется.

============================================

Не ошибка, просто упрощаем код:

1. в файле cart.php

заменяем


if ( isset ( $_SESSION["log"] ))
//taking products from database
{
$q = db_query("select itemID, Quantity FROM ".SHOPPING_CARTS_TABLE." WHERE customerID=".( int ) regGetIdByLogin($_SESSION["log"]));
while ( $row = db_fetch_row($q)) {
$q1 = db_query("select productID from ".SHOPPING_CART_ITEMS_TABLE." where itemID=".( int ) $row["itemID"]);
$r1 = db_fetch_row($q1);
$variants = GetConfigurationByItemId($row["itemID"]);
$k += GetPriceProductWithOption($variants, $r1["productID"]) * $row["Quantity"];
$cnt += $row["Quantity"];
}
}
else
if ( isset ( $_SESSION["gids"] ))
//...session vars
{
for ( $i = 0; $i < count($_SESSION["gids"]); $i++ ) {
if ( $_SESSION["gids"][$i] ) {
$t = db_query("select Price FROM ".PRODUCTS_TABLE." WHERE productID=".( int ) $_SESSION["gids"][$i]);
$rr = db_fetch_row($t);
$sum = $rr["Price"];
// $rr["Price"]
foreach ( $_SESSION["configurations"][$i] as $varconf ) {
$q1 = db_query("select price_surplus from ".PRODUCTS_OPTIONS_SET_TABLE." where variantID=".( int ) $varconf." AND productID=".( int ) $_SESSION["gids"][$i]);
$r1 = db_fetch_row($q1);
$sum += $r1["price_surplus"];
}
$k += $_SESSION["counts"][$i] * $sum;
$cnt += $_SESSION["counts"][$i];
}
}
}


на


$k = $resCart["total_price"];
#$k = $resCart["total_price"] - $resDiscount["discount_standart_unit"]; // если хотим видеть в корзине сумму сразу со скидкой
foreach ($resCart["cart_content"] as $rc) $cnt += $rc["quantity"];



2. в файле shopping_cart_info.php

заменяем


if (isset($_SESSION["log"])) //taking products from database
{
$q = db_query("select itemID, Quantity FROM ".SHOPPING_CARTS_TABLE.
" WHERE customerID=".regGetIdByLogin($_SESSION["log"]));
while ($row = db_fetch_row($q))
{
$q1=db_query("select productID from ".SHOPPING_CART_ITEMS_TABLE.
" where itemID=".$row["itemID"]);
$r1=db_fetch_row($q1);
if($r1["productID"]){
$variants=GetConfigurationByItemId( $row["itemID"] );
$k += GetPriceProductWithOption($variants, $r1["productID"])*$row["Quantity"];
$cnt+=$row["Quantity"];
}
}
}
else
if (isset($_SESSION["gids"])) //...session vars
{
for ($i=0; $i<count($_SESSION["gids"]); $i++)
{
if ($_SESSION["gids"][$i])
{
$t = db_query("select Price FROM ".PRODUCTS_TABLE." WHERE productID=".(int)$_SESSION["gids"][$i]);
$rr = db_fetch_row($t);

$sum=$rr["Price"];

// $rr["Price"]
foreach( $_SESSION["configurations"][$i] as $vars )
{
$q1=db_query("select price_surplus from ".PRODUCTS_OPTIONS_SET_TABLE.
" where variantID=".(int)$vars." AND productID=".(int)$_SESSION["gids"][$i]);
$r1=db_fetch_row($q1);
$sum+=$r1["price_surplus"];
}

$k += $_SESSION["counts"][$i]*$sum;
$cnt += $_SESSION["counts"][$i];
}
}
}


на


$resCart = cartGetCartContent();
$k = $resCart["total_price"];
#$resDiscount = dscCalculateDiscount($resCart["total_price"], isset ( $_SESSION["log"] ) ? $_SESSION["log"] : ""); // если хотим видеть в корзине сумму сразу со скидкой
#$k = $resCart["total_price"] - $resDiscount["discount_standart_unit"];
foreach ($resCart["cart_content"] as $rc) $cnt += $rc["quantity"];


=============================================

Не ошибка, хотя как посмотреть. Дополнение резко сокращает количество SQL-запросов при сохранении настроек товаров и категорий. Актуально для сайтов с большим количеством категорий. Например, штатно на тысяче категорий будет 16тысяч (!!!) SQL-запросов. Здесь, насколько я помню, четыре запроса не зависимо от количества категорий.


Установка:

В файле category_functions.php

1. в функции update_psCount

строку


update_pCount($parent);


заменяем на


update_pCount_new($parent);


2. куда-нибудь рядом добавляем две функции


function update_sCount_new($parent, $counts = array(1 => array ('subcats' => 0,'admin_count' => 0,'customer_count' => 0)))
{
global $mc;
foreach (array_keys ($mc,(int)$parent) as $val)
{
$counts[$val]['subcats'] = count(array_keys($mc, $val));
$counts[$val]['admin_count'] = 0;
$counts[$val]['customer_count'] = 0;
if ($counts[$val]['subcats']) $counts = update_sCount_new($val,$counts);
}
return $counts;
}

function update_pCount_new($parent)
{
global $fc;
$qstr = array(
"SELECT categoryID, COUNT(*) AS admcount, COUNT(NULLIF(enabled,0)) AS count FROM ".PRODUCTS_TABLE." GROUP BY categoryID",
"SELECT pc.categoryID, COUNT(*) AS admcount, COUNT(NULLIF(enabled,0)) AS count FROM ".CATEGORIY_PRODUCT_TABLE." AS pc JOIN ".PRODUCTS_TABLE." USING (productID) GROUP BY pc.categoryID");
$counts = update_sCount_new($parent);
foreach ($qstr as $str)
{
$data = db_query($str);
while ($row=db_fetch_assoc($data))
{
$categoryID = (int)$row['categoryID'];
while ($categoryID)
{
$counts[$categoryID]['admin_count'] += (int)$row['admcount'];
$counts[$categoryID]['customer_count'] += (int)$row['count'];
$categoryID = $fc[$categoryID]['parent'];
}
}
}
$data = db_query("SELECT categoryID, subcount, products_count, products_count_admin FROM ".CATEGORIES_TABLE);
while ($row = db_fetch_assoc($data))
{
$categoryID = (int)$row['categoryID'];
if ((int)$row['subcount'] != $counts[$categoryID]['subcats'] || (int)$row['products_count'] != $counts[$categoryID]['customer_count'] || (int)$row['products_count_admin'] != $counts[$categoryID]['admin_count'])
db_query("UPDATE ".CATEGORIES_TABLE." SET subcount=".$counts[$categoryID]['subcats'].", products_count=".$counts[$categoryID]['customer_count'].", products_count_admin=".$counts[$categoryID]['admin_count']." WHERE categoryID=$categoryID");
}
}

  • 6
http://cpu.badisoft.ru (тестовый сайт), http://badisoft.ru (модули)

#2 Lada

    Продвинутый пользователь

  • Download User
  • PipPipPip
  • 107 сообщений
Репутация: 7
Начинающий
  • ГородЧита

Отправлено 11 November 2014 - 03:54 PM

Большое Вам спасибо, особенно было актуально то, что незарегистрированный пользователь не мог скачать купленный им электронный товар.
Из-за этого приходилось выставлять ОБЯЗАТЕЛЬНУЮ регистрацию..
А когда в магазине товар смешанный - цифровой и физический, то теряли натурально большой процент клиентов, которые брали физические товары и их смущала эта обязательная регистрация..
  • 0

#3 badisoft

    Продвинутый пользователь

  • Assistent vsupport.club
  • PipPipPip
  • 5075 сообщений
Репутация: 786
Мастер

Отправлено 11 November 2014 - 04:06 PM

Большое Вам спасибо, особенно было актуально то, что незарегистрированный пользователь не мог скачать купленный им электронный товар.

Это единственная найденная не мной ошибка. Так что спасибо не мне :).
  • 1
http://cpu.badisoft.ru (тестовый сайт), http://badisoft.ru (модули)

#4 Jeck2000

    Продвинутый пользователь

  • Assistent vsupport.club
  • PipPipPip
  • 159 сообщений
Репутация: 8
Начинающий
  • ГородСанкт-Петербург

Отправлено 13 November 2014 - 08:07 PM

Огромное спасибо за оптимизацию запросов при сохранении товара или категории при условии огромного кол-ва категорий. В разы ускорило процесс сохранения
  • 0

#5 badisoft

    Продвинутый пользователь

  • Assistent vsupport.club
  • PipPipPip
  • 5075 сообщений
Репутация: 786
Мастер

Отправлено 18 November 2014 - 01:46 PM

Ошибка в исправлении ошибки :).
Функция
function GetPriceProductWithOption($variants, $productID)
при пустом массиве $variants (у товара нет вариантов характеристик) выполняла неверный запрос. На результат не влияет, но появляется запись в логе ошибок. Исправлено.
  • 0
http://cpu.badisoft.ru (тестовый сайт), http://badisoft.ru (модули)

#6 Revived

    Продвинутый пользователь

  • Assistent vsupport.club
  • PipPipPip
  • 59 сообщений
Репутация: 0
Начинающий

Отправлено 19 November 2014 - 11:23 PM

Спасибо, раньше долго удалялось и сохранялось
  • 0

#7 FusSheva

    Продвинутый пользователь

  • Assistent vsupport.club
  • PipPipPip
  • 210 сообщений
Репутация: 7
Начинающий

Отправлено 18 December 2014 - 03:52 PM

Дополнение резко сокращает количество SQL-запросов при сохранении настроек товаров и категорий.


Вы толковый специалист badisoft, не раз в этом убеждался.
Добавление картинок (что подразумевает каждый раз сохранение товара) теперь добавляются на ура быстро!
Браво, badisoft !!! Большое человеческое спасибо!
  • 1
Каждый человек способен на многое. Но к сожалению, не каждый знает на что он способен.

#8 badisoft

    Продвинутый пользователь

  • Assistent vsupport.club
  • PipPipPip
  • 5075 сообщений
Репутация: 786
Мастер

Отправлено 16 April 2015 - 11:03 PM

Хех... Неисчерпаем ShopCMS на мелкие и не очень ошибки :).

При электронной торговле в детальном описании некорректно показывается размер файла.

В файле product_detailed.php есть такой код


$size = filesize("core/files/".$a["eproduct_filename"]);
if ($size > 1000) $size = round ($size / 1000);
$a["eproduct_filesize"] = $size." Kb";


Очевидно, что если размер файла меньше 1000 байт (например, 700байт), то он будет показан как 700Кб.
Лечение:


#$size = filesize("core/files/".$a["eproduct_filename"]);
#if ($size > 1000) $size = round ($size / 1000);
#$a["eproduct_filesize"] = $size." Kb";
$a["eproduct_filesize"] = ceil(filesize("core/files/".$a["eproduct_filename"])/1024.0).'кб';


При этом размер будет откругляться до килобайта в большую сторону, т.е. 300байт будет показано как 1кб, а 2049байт как 3кб.

Отдельно странно, что в ShopCMS в разных местах разный размер килобайта :).
Здесь он 1000 байт, а в функции _sendOrderNotifycationToCustomer(), отсылающей письмо клиенту уже 1024 байта, т.к. там размер файла для показа в мегабайтах делится на 1048576 (1024х1024).
  • 1
http://cpu.badisoft.ru (тестовый сайт), http://badisoft.ru (модули)

#9 badisoft

    Продвинутый пользователь

  • Assistent vsupport.club
  • PipPipPip
  • 5075 сообщений
Репутация: 786
Мастер

Отправлено 03 August 2015 - 08:48 PM

Хех... Интересно, я помру раньше, чем ошибки кончатся? :)

Вне зависимости от установки галки "Разрешить покупателям оставлять мнения о товаре" прямая ссылка с тем самым "оставлять мнение о товаре" (site.ru/index.php?productID=XXX&discuss=yes) вполне работает. Со всеми вытекающими по части спама, хотя его никто кроме админа и не увидит. Лечение простое. В файле product_discussion.php в начале добавляем

# BEGIN устранение доступности формы обсуждения, если она запрещена
if (CONF_USE_DISCUSS)
{
# END устранение доступности формы обсуждения, если она запрещена

а в конце

# BEGIN устранение доступности формы обсуждения, если она запрещена
}
# END устранение доступности формы обсуждения, если она запрещена

  • 3
http://cpu.badisoft.ru (тестовый сайт), http://badisoft.ru (модули)

#10 FusSheva

    Продвинутый пользователь

  • Assistent vsupport.club
  • PipPipPip
  • 210 сообщений
Репутация: 7
Начинающий

Отправлено 03 August 2015 - 10:16 PM

Живите долго! Вы нам нужны! :)
Проверил, теперь при запрете выбрасывает на главную (без записи).
  • 0
Каждый человек способен на многое. Но к сожалению, не каждый знает на что он способен.

#11 badisoft

    Продвинутый пользователь

  • Assistent vsupport.club
  • PipPipPip
  • 5075 сообщений
Репутация: 786
Мастер

Отправлено 17 September 2015 - 01:25 PM

Еще пара ошибок (они уже были описаны в других ветках).

=============================
Штатная ошибка: При импорте из CSV если в каталоге присутствует наименование взятое в кавычки "Товар" то импорт не обновляет данные товары а считает их как новыми, кавычки не распознает

Причина: Название товара перед сохранением в таблицу обрабатывается функцией htmlspecialchars, т.е., к примеру, про'вер"ка будет лежать в таблице как про&#039;вер&quot;ка, но при идентификации товара этого преобразования не делается, т.е. сравнение выглядит как name LIKE 'про\'вер"ка'. Естественно, названия не совпадают и товар заносится как новый.

Исправление:

В файле catalog_import_functions.php в функции _importProduct в строке



" LIKE '".xEscSQL(trim($row[$identity_column]))."'");



заменяем xEscSQL на ToText.

Таких строк там две, достаточно заменить в первой, но можно и в обоих (если в коде товара тоже могут быть кавычки).

============================

Хехе... В 3.1.3 не только старые ошибки не исправлены, но и новых добавлено. Я уже две нашел :).
Исправления:

1. файл product_detailed.tpl.html
Используется смарти-массив $popular_products вместо $product_related, в результате вместо фотки товара в "рекомендуемых" получаем фотку хрен знает чего :).


#<a href="{if $smarty.const.CONF_MOD_REWRITE eq 1}product_{$product_related[i].productID}.html{else}index.php?productID={$product_related[i].productID}{/if}"><img src="data/{$popular_products[i].filename}" alt="" class="thumbnail"></a>
<a href="{if $smarty.const.CONF_MOD_REWRITE eq 1}product_{$product_related[i].productID}.html{else}index.php?productID={$product_related[i].productID}{/if}"><img src="data/{$product_related[i].filename}" alt="" class="thumbnail"></a>


2. файл product_detailed.php
Ну, тут очевидно. Просто перепутан массив.


#$r["filename"] = "small/".$row["filename"];
$r["filename"] = "small/".$r["filename"];


============================
  • 0
http://cpu.badisoft.ru (тестовый сайт), http://badisoft.ru (модули)

#12 qwezi

    Новичок

  • Пользователи
  • Pip
  • 2 сообщений
Репутация: 0
Начинающий

Отправлено 18 September 2015 - 09:24 AM

Добрый день. подскажите, пожалуйста, как исправить:
Если писать названия блоков, название сайта, кейвордс, название доставки и т.д. на Русском языке, после сохранения остается пустое поле.
Как это исправить?
  • 0

#13 badisoft

    Продвинутый пользователь

  • Assistent vsupport.club
  • PipPipPip
  • 5075 сообщений
Репутация: 786
Мастер

Отправлено 18 September 2015 - 10:06 AM

Как это исправить?

Поставить PHP версии 5.3 или ниже.

PS. На форуме есть "поиск". Проблема описана уже раз десять, если не больше. А эта тема совсем о другом - о ШТАТНЫХ ошибках.
  • 0
http://cpu.badisoft.ru (тестовый сайт), http://badisoft.ru (модули)

#14 badisoft

    Продвинутый пользователь

  • Assistent vsupport.club
  • PipPipPip
  • 5075 сообщений
Репутация: 786
Мастер

Отправлено 22 September 2015 - 02:11 PM

Написал импорт из CSV, которому наплевать на размер CSV, хоть гигабайт и стопицоттыщ товаров, т.к. импорт идет АЯКС-запросами по заданному количеству строк из CSV-файла. Но это так, вводная. Пока писал, нашел вопиющую ошибку при импорте характеристик. Характеристики идут последними столбцами. Перед ними столбцы с фотографиями. Так вот сколько столбцов с фотографиями - столько будет потеряно (не импортировано) последних столбцов характеристик.

Это один из вариантов массива $updated_extra_option, который передается в функцию _importExtraOptionValues. Столбцов с фотографиями в этом CSV-файле двадцать, а характеристик всего семь, так нагляднее.
array (
  0 => 0,
  1 => 0,
  2 => 0,
  3 => 0,
  4 => 0,
  5 => 0,
  6 => 0,
  7 => 0,
  8 => 0,
  9 => 0,
  10 => 0,
  11 => 0,
  12 => 0,
  13 => 0,
  14 => 0,
  15 => 0,
  16 => 0,
  17 => 0,
  18 => 0,
  19 => 0,
  20 => 0,
  21 => 0,
  22 => 0,
  23 => 0,
  24 => 0,
  38 => '75',
  39 => '76',
  40 => '77',
  41 => '78',
  42 => '79',
  43 => '80',
  44 => '81',
)
Элементы 38-44 это номера характеристик (optionID), а ключи - номера столбцов. Обращу внимание, что элементов 25-37 нет. Так уж написано в ShopCMS, что столбцы с фотографиями в этом массиве отсутствуют.
А это цикл обработки этого массива в той же функции:

for ($j=0; $j<count($updated_extra_option); $j++)
{
if (isset($updated_extra_option[$j]) && $updated_extra_option[$j]) //a column which is an extra option
...

Понятно, да? функция count честно показывает, что в массиве 32 элемента и цикл НИКОГДА не дойдет до элементов 38-44, т.е. до столбцов с характеристиками товара.

Решение:

# BEGIN исправляем ошибку импорта характеристик товара
/*
for ($j=0; $j<count($updated_extra_option); $j++)
{
if (isset($updated_extra_option[$j]) && $updated_extra_option[$j]) //a column which is an extra option
{
$optionID = $updated_extra_option[$j];
*/
foreach ($updated_extra_option as $j => $optionID)
{
if ($optionID) //a column which is an extra option
{
# END исправляем ошибку импорта характеристик товара


PS. Кстати, кто поделится CSV-файлом на 100500тыщ каких-нибудь товаров (для проверки) - буду благодарен :).
  • 0
http://cpu.badisoft.ru (тестовый сайт), http://badisoft.ru (модули)

#15 badisoft

    Продвинутый пользователь

  • Assistent vsupport.club
  • PipPipPip
  • 5075 сообщений
Репутация: 786
Мастер

Отправлено 30 September 2015 - 09:03 PM

Покупателем нашлась еще одна ошибка. Если оплатить заказ (статус заказа изменится на "оплачен"), а потом перейти по ссылке из емейла "отменить заказ", то статус заказа изменится на отменен. И сколько раз перейти по ссылке, столько раз он будет отменен с соответствующим появлением записи в истории изменения статусов заказа.

Пока только констатирую ошибку, не изучал и не исправлял.
  • 0
http://cpu.badisoft.ru (тестовый сайт), http://badisoft.ru (модули)

#16 Jeck2000

    Продвинутый пользователь

  • Assistent vsupport.club
  • PipPipPip
  • 159 сообщений
Репутация: 8
Начинающий
  • ГородСанкт-Петербург

Отправлено 11 October 2015 - 01:55 PM

Штатная ошибка: При импорте из CSV варианты характеристик, содержащие символы '"&amp;lt;&amp;gt;&amp;amp; двоятся, т.е. создаются столько раз, сколько товаров с таким вариантом характеристики.


badisoft, такой вопрос, а нет ли там еще какого-нибудь глюка с импортом в плане присутствия символа "/" в названии? Пробую импортировать исправленный CSV файл (исправленный в смысле отредактированный под мои нужды), так вот то же, при импорте товары добавляются как новые. Исправление как у тебя написано сделал (замена на ToText), но это не повлияло на результат. Товары добавились как новые в главную, хотя имеют абсолютно идентичные названия
  • 0

#17 badisoft

    Продвинутый пользователь

  • Assistent vsupport.club
  • PipPipPip
  • 5075 сообщений
Репутация: 786
Мастер

Отправлено 22 October 2015 - 06:39 PM

та-да-да-дам! И почему я не удивлен? в общем, еще одна.

===================
Штатная ошибка.
В таблице товаров и в настройке категории при переносе товаров в другую категорию перенос осуществляется перезаписью categoryID в таблице товаров, т.е. меняется только основная категория, а доп.категории остаются неизменными.
В результате получаем следующую картину: товар показывается в списке товаров доп.категории, но при попытке переноса в другую остается не перенесенным, ведь информация о доп.категории при этом не меняется.

Исправление:

1. для таблицы товаров:
в файле catalog_products_categories.php
вместо


elseif ( $_POST["add_command"]=="prod_move"){db_query( "UPDATE ".PRODUCTS_TABLE." SET categoryID = ".(int)$_POST["prod_categoryID"]." WHERE productID=".(int)$key);}


вставляем


# BEGIN исправляем перенос из добавочной категории
#elseif ( $_POST["add_command"]=="prod_move"){db_query( "UPDATE ".PRODUCTS_TABLE." SET categoryID = ".(int)$_POST["prod_categoryID"]." WHERE productID=".(int)$key);}
elseif ( $_POST["add_command"]=="prod_move")
{
$prd = db_fetch_assoc(db_query("SELECT categoryID FROM ".PRODUCTS_TABLE." WHERE productID=".(int)$key." LIMIT 1"));
if (isset($_GET['search']) || !isset($_GET['categoryID']) || $prd['categoryID']==(int)$_GET['categoryID']) // это основная категория товара (либо результат поиска, где категория у товаров разная)
db_query( "UPDATE ".PRODUCTS_TABLE." SET categoryID = ".(int)$_POST["prod_categoryID"]." WHERE productID=".(int)$key);
else // это доп категория товара
db_query( "UPDATE ".CATEGORIY_PRODUCT_TABLE." SET categoryID = ".(int)$_POST["prod_categoryID"]." WHERE categoryID=".(int)$_GET['categoryID']." AND productID=".(int)$key);
}
# END исправляем перенос из добавочной категории



2. для редактирования категории (там есть пункт "Перенести все товары из этой категории в [...]"):
в файле admin.php
после


db_query("update ".PRODUCTS_TABLE." SET categoryID=".(int)$_POST["removeto"]." WHERE categoryID=".(int)$_POST["must_delete"]);


вставляем


# BEGIN исправляем перенос из добавочной категории
db_query("update ".CATEGORIY_PRODUCT_TABLE." SET categoryID=".(int)$_POST["removeto"]." WHERE categoryID=".(int)$_POST["must_delete"]);
# END исправляем перенос из добавочной категории

  • 0
http://cpu.badisoft.ru (тестовый сайт), http://badisoft.ru (модули)

#18 badisoft

    Продвинутый пользователь

  • Assistent vsupport.club
  • PipPipPip
  • 5075 сообщений
Репутация: 786
Мастер

Отправлено 28 October 2015 - 02:57 PM

Хм... Иногда очень хочется посмотреть на программиста, который писал ShopCMS. Сколько у него рук и откуда растут :).
Есть в order_amount_functions.php такая функция.

function oaGetClearPrice( $cartContent )
{
$res = 0;
for( $i=0; $i<count($cartContent["cart_content"]); $i++ )
{
$cartItem = $cartContent["cart_content"][$i];
$res += $cartItem["quantity"]*$cartItem["costUC"];
}
return $res;
}

Вроде, совершенно нормальная функция, правда?
Явно считает некую общую сумму.
Но есть нюанс.
Эта считаемая сумма (уже подсчитанная ранее, в функции GetCartContent) передается в эту функцию в этом же массиве данных - $cartContent["total_price"].
  • 0
http://cpu.badisoft.ru (тестовый сайт), http://badisoft.ru (модули)

#19 badisoft

    Продвинутый пользователь

  • Assistent vsupport.club
  • PipPipPip
  • 5075 сообщений
Репутация: 786
Мастер

Отправлено 07 November 2015 - 09:10 PM

Покупателем нашлась еще одна ошибка. Если оплатить заказ (статус заказа изменится на "оплачен"), а потом перейти по ссылке из емейла "отменить заказ", то статус заказа изменится на отменен. И сколько раз перейти по ссылке, столько раз он будет отменен с соответствующим появлением записи в истории изменения статусов заказа. Пока только констатирую ошибку, не изучал и не исправлял.

Штатная ошибка.
Заказу со статусом доставлено, т.е. по сути закрытому заказу клиент может сменить статус на "Отменен" если уже после оплаты кликнет по ссылке в полученном емейле "отменить заказ".
Вроде и незачем ему кликать, заказ оплатил, товар получил, но вот уже два раза :).

Исправление:

в файле order_functions.php в функции deactivate_order

вместо


$q = db_query("select orderID FROM ".ORDERS_TABLE." WHERE custlink='".xEscSQL($actlink)."' ");
if($pql = db_fetch_row($q)){


вставляем


# BEGIN не даем отменить уже оплаченный заказ
#$q = db_query("select orderID FROM ".ORDERS_TABLE." WHERE custlink='".xEscSQL($actlink)."' ");
#if($pql = db_fetch_row($q)){
$q = db_query("select orderID,statusID FROM ".ORDERS_TABLE." WHERE custlink='".xEscSQL($actlink)."' ");
if($pql = db_fetch_row($q) && $pql["statusID"] != ostGetCompletedOrderStatus()){
# END не даем отменить уже оплаченный заказ

  • 0
http://cpu.badisoft.ru (тестовый сайт), http://badisoft.ru (модули)

#20 badisoft

    Продвинутый пользователь

  • Assistent vsupport.club
  • PipPipPip
  • 5075 сообщений
Репутация: 786
Мастер

Отправлено 08 December 2015 - 09:10 PM

Очередная обалденная штатная ошибка, которая не понятно почему до сих пор никем не была замечена.
В user.js есть JS-функция _formatPrice, она форматирует цену товара исходя из заданного округления валюты.
Эта функция выводит цену товара как минимум в категории и подробном описании.
Округление валюты в админке мы можем задать как угодно. Положительным числом (сколько знаков ПОСЛЕ запятой) или отрицательным числом (сколько знаков ПЕРЕД запятой). Скажем, при заданном округлении "-1" цена "127.16" должна округлиться до "130". Но эта функция берет округление ПО МОДУЛЮ! Без учета знака! Т.е. "-1" ничем не отличается от "1" и "127.16" будет округлено до "127.2". Что и было замечено одним из клиентов.

Исправление:
function _formatPrice( number, decimals, dec_point, thousands_sep ) {
// BEGIN исправление ошибки при "отрицательном" округлении в настройке валют
	var c = Math.pow(10,decimals);
	var s = Math.round(number*c)/c;
	s = s.toString();
	var d = (s.split("."))[1];
	s = (s.split("."))[0];
	var t = '';
	thousands_sep = (typeof thousands_sep == "undefined")?' ':thousands_sep;
	dec_point = (typeof dec_point == "undefined")?'.':dec_point;
	for (var i=s.length-1;i>=0;i--)
		{
		t = s.charAt(i)+t;
		if ((s.length-i)%3==0 && i>0) t = thousands_sep+t;
		}
	s = t + ((typeof d == "undefined")?'':(dec_point+d));
/*	
	var n = number, prec = decimals;
	n = !isFinite(+n) ? 0 : +n;
	prec = !isFinite(+prec) ? 0 : Math.abs(prec);
	var sep = (typeof thousands_sep == "undefined") ? ' ' : thousands_sep;
	var dec = (typeof dec_point == "undefined") ? '.' : dec_point;

	var s = (prec > 0) ? n.toFixed(prec) : Math.round(n).toFixed(prec);

	var abs = Math.abs(n).toFixed(prec);
	var _, i;

	if (abs >= 1000) {
		_ = abs.split(/\D/);
		i = _[0].length % 3 || 3;

		_[0] = s.slice(0,i + (n < 0)) +
			  _[0].slice(i).replace(/(\d{3})/g, sep+'$1');

		s = _.join(dec);
	} else {
		s = s.replace('.', dec);
	}
*/
// END исправление ошибки при "отрицательном" округлении в настройке валют
	return s;
}

PS. Я, честно говоря, офигеваю. Это не ошибка и не опечатка, это специально так написано. Занахера?
  • 0
http://cpu.badisoft.ru (тестовый сайт), http://badisoft.ru (модули)