Защита склада при одновременной покупке одного товара двумя покупателями
#1
Отправлено 20 May 2016 - 11:25 AM
Для меня стало открытием, не смотря на многолетний опыт работы с ShopCMS, отсутствие защиты склада при одновременной покупке одного товара двумя покупателями.
Например, имеем на складе товар в количестве 100 шт.
Покупатель A кинул в корзину 90 шт. этого товара.
Покупатель Б кинул в корзину 90 шт. этого же товара и оформил заказ.
Затем покупатель A оформил заказ - то , что уже было в его корзине 90 шт. (не пересчитывал) того самого товара
В итоге склад уходит в минус
Кто-нибудь разбирался с этой ситуацией?
доработка функционала
#2
Отправлено 20 May 2016 - 12:22 PM
Странно. Ведь на этапе окончательного оформления заказа, насколько я помню, еще раз проверяется, есть ли требуемое количество товара на складе. Если нет, то выдаетсяКто-нибудь разбирался с этой ситуацией?
define('STRING_PRODUCT_REMOVED', '<b>Ваш заказ не может быть оформлен!</b><br>В процессе покупки товара он закончился на складе.<br>Пожалуйста, проверьте состояние корзины и сформируйте заказ заново.');
Как я понимаю, как раз для таких ситуаций и сделано. Если товар на складе один, то есть шансы одновременного его оформления.
#3
Отправлено 20 May 2016 - 12:22 PM
#4
Отправлено 20 May 2016 - 01:12 PM
Зачем так хитро? Куда проще в две вышеописанные функции вставить проверку на количество товара. Аналогично функции cartAddToCart(), где используется штатная функция получения количества на кладена корзину чекер склада перед оформлением, если у человека висит в корзине пол года
$is = GetProductInStockCount( $productID );
А на последнем этапе есть проверка, но какая-то странная. Не на наличие на складе товара в нужном количестве, а на наличие товара. Т.е. проверка есть, но вывод надписи из моего первого сообщения (и не оформление заказа) произойдет только если товара нет вообще. Меньше одного. А если десять, а в корзине двадцать, то заказ оформится.
order4_confirmation.php, order4_confirmation_quick.php:
if ( CONF_CHECKSTOCK ) {
$cartContent = cartGetCartContent();
$rediractflag = false;
foreach ( $cartContent["cart_content"] as $cartItem ) {
// if conventional ordering
if ( isset ( $_SESSION["log"] )) {
$productID = GetProductIdByItemId($cartItem["id"]);
$q = db_query("select name, in_stock FROM ".PRODUCTS_TABLE." WHERE productID=".( int ) $productID);
$left = db_fetch_row($q);
if ( $left["in_stock"] < 1 ) {
$rediractflag = true;
db_query("DELETE FROM ".SHOPPING_CARTS_TABLE." WHERE customerID=".regGetIdByLogin($_SESSION["log"])." AND itemID=".( int ) $cartItem["id"]);
db_query("DELETE FROM ".SHOPPING_CART_ITEMS_TABLE." where itemID=".( int ) $cartItem["id"]);
db_query("DELETE FROM ".SHOPPING_CART_ITEMS_CONTENT_TABLE." where itemID=".( int ) $cartItem["id"]);
db_query("DELETE FROM ".ORDERED_CARTS_TABLE." where itemID=".( int ) $cartItem["id"]);
}
}
else
// if quick ordering
{
$productID = $cartItem["id"];
$q = db_query("select name, in_stock FROM ".PRODUCTS_TABLE." WHERE productID=".( int ) $productID);
$left = db_fetch_row($q);
if ( $left["in_stock"] < 1 ) {
$rediractflag = true;
$res = DeCodeItemInClient($productID);
$i = SearchConfigurationInSessionVariable($res["variants"], $res["productID"]);
if ( $i != - 1 )
$_SESSION["gids"][$i] = 0;
}
}
}
if ( $rediractflag ) Redirect("index.php?product_removed=yes");
}
В общем, странные люди писали ShopCMS. if/else c практически одинаковым кодом. SQL-запрос и обвязка вместо применения имеющейся функции (см.выше). В принципе, вот вместо этого кода и напрашивается проверка на соответствие текущему количеству товара. Ну а потом либо в таблице, либо в переменной сессии скорректировать. Хотя я бы сделал проверку разнесенно в двух вышеуказанных функциях переноса корзины в заказ. Там оно как-то больше к месту.
#5
Отправлено 22 May 2016 - 06:07 PM
На каждом этапе оформления заказа (доставка, оплата, подтверждение) происходит проверка на минимальную сумму заказа.
Вот рядом с этой проверкой и добавить проверку на наличие достаточного количества товара на складе.
Т.е. в файл cart_functions.php добавляем функцию
function cartCheckSufficientAmountOfStock(){ $cart_content = cartGetCartContent(); $cart_content = $cart_content["cart_content"]; foreach( $cart_content as $cart_item ) { $is = GetProductInStockCount( $cart_item["productID"] ); if ( $is < $cart_item["quantity"] ) return false; } return true; }
а в order2_shipping.php, order2_shipping_quick.php, order3_billing.php, order3_billing_quick.php, order4_confirmation.php, order4_confirmation_quick.php добавить вызов функции
if(!cartCheckSufficientAmountOfStock()) Redirect("index.php?product_removed=yes");
доработка функционала
#6
Отправлено 22 May 2016 - 06:42 PM
Да? Не обращал внимания, что на каждом этапе. Полезно. Спасибо!На каждом этапе оформления заказа (доставка, оплата, подтверждение) происходит проверка на минимальную сумму заказа.
Я бы не стал использовать функцию cartGetCartContent() для того, чтобы получить список ProductID в корзине. Из пушки по воробьям. Там слишком много лишних SQL-запросов, дающих кучу не нужной в данном случае информации. Да и вообще функция штатно через задницу написана (повторные вызовы того, что уже получено выше).Вот рядом с этой проверкой и добавить
Для получения списка ProductID в регистрированной корзине достаточно двух SQL-запросов. Один для получения массива item-ов, второй для получения по ним массива productID. Или даже одного составного (вложенного) запроса, он не будет ресурсоемким в силу простоты и небольшого количества записей в таблице корзины. Ну а при не регистрированном клиенте все еше проще. В общем, я бы написал отдельный код или функцию для получения списка productID в корзине. Понятно, что при оформлении заказа количество SQL-запросов не особенно и критично, но просто для красоты процесса.
#7
Отправлено 23 May 2016 - 09:13 PM
#8
Отправлено 23 May 2016 - 09:18 PM
И это все, что нужно знать об официальной поддержке ShopCMS.Максим » 23 дек 2009, 15:27 Спасибо, программисты сегодня посмотрят, я потом отпишу что скажут. Но что-то я не уверен что в скрипте последней версии есть такие проблемы.