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


Защита склада при одновременной покупке одного товара двумя покупателями

ошибка оформление заказа

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

#1 namer

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

  • Download User
  • PipPipPip
  • 45 сообщений
Репутация: 16
Начинающий
  • ГородКрасноярск

Отправлено 20 May 2016 - 11:25 AM

Доброго дня, коллеги! Давно не заглядывал.

Для меня стало открытием, не смотря на многолетний опыт работы с ShopCMS, отсутствие защиты склада при одновременной покупке одного товара двумя покупателями.

Например, имеем на складе товар в количестве 100 шт.
Покупатель A кинул в корзину 90 шт. этого товара.
Покупатель Б кинул в корзину 90 шт. этого же товара и оформил заказ.
Затем покупатель A оформил заказ - то , что уже было в его корзине 90 шт. (не пересчитывал) того самого товара

В итоге склад уходит в минус

Кто-нибудь разбирался с этой ситуацией?
  • 0
Установка, настройка
доработка функционала
Изображение

#2 badisoft

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

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

Отправлено 20 May 2016 - 12:22 PM

Кто-нибудь разбирался с этой ситуацией?

Странно. Ведь на этапе окончательного оформления заказа, насколько я помню, еще раз проверяется, есть ли требуемое количество товара на складе. Если нет, то выдается

define('STRING_PRODUCT_REMOVED', '<b>Ваш заказ не может быть оформлен!</b><br>В процессе покупки товара он закончился на складе.<br>Пожалуйста, проверьте состояние корзины и сформируйте заказ заново.');

Как я понимаю, как раз для таких ситуаций и сделано. Если товар на складе один, то есть шансы одновременного его оформления.
  • 0
http://cpu.badisoft.ru (тестовый сайт), http://badisoft.ru (модули)

#3 zrom

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

  • Download User
  • PipPipPip
  • 69 сообщений
Репутация: 16
Начинающий

Отправлено 20 May 2016 - 12:22 PM

на корзину чекер склада перед оформлением, если у человека висит в корзине пол года, а товара уже нет, закрашиваем серым цветом, мол закончился извините. ну и либо удалять из корзины, либо не передавать в заказ. уйдет в минус, только если одновременно в сию секунду/минуту оформить заказ, но для меня редкость такое.
  • 0

#4 badisoft

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

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

Отправлено 20 May 2016 - 01:12 PM

Хотя нет, я не прав (глянув функцию order_processing()). Это сообщение выдается как раз на первом этапе оформления. А вот завершение оформления заказа, т.е. собственно само создание заказа не имеет никаких проверок на наличие товара на текущий момент. Ни в _moveSessionCartContentToOrderedCart() (нерег.клиенты), ни в cartMoveContentFromShoppingCartsToOrderedCarts() (рег.клиенты). Т.е. если клиент завис на этапе выбора отправки, оплаты или завершения оформления, то товар за это время могут весь купить, но заказ все равно будет создан :).

на корзину чекер склада перед оформлением, если у человека висит в корзине пол года

Зачем так хитро? Куда проще в две вышеописанные функции вставить проверку на количество товара. Аналогично функции 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-запрос и обвязка вместо применения имеющейся функции (см.выше). В принципе, вот вместо этого кода и напрашивается проверка на соответствие текущему количеству товара. Ну а потом либо в таблице, либо в переменной сессии скорректировать. Хотя я бы сделал проверку разнесенно в двух вышеуказанных функциях переноса корзины в заказ. Там оно как-то больше к месту.
  • 0
http://cpu.badisoft.ru (тестовый сайт), http://badisoft.ru (модули)

#5 namer

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

  • Download User
  • PipPipPip
  • 45 сообщений
Репутация: 16
Начинающий
  • ГородКрасноярск

Отправлено 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");

  • 0
Установка, настройка
доработка функционала
Изображение

#6 badisoft

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

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

Отправлено 22 May 2016 - 06:42 PM

На каждом этапе оформления заказа (доставка, оплата, подтверждение) происходит проверка на минимальную сумму заказа.

Да? Не обращал внимания, что на каждом этапе. Полезно. Спасибо!

Вот рядом с этой проверкой и добавить

Я бы не стал использовать функцию cartGetCartContent() для того, чтобы получить список ProductID в корзине. Из пушки по воробьям. Там слишком много лишних SQL-запросов, дающих кучу не нужной в данном случае информации. Да и вообще функция штатно через задницу написана (повторные вызовы того, что уже получено выше).
Для получения списка ProductID в регистрированной корзине достаточно двух SQL-запросов. Один для получения массива item-ов, второй для получения по ним массива productID. Или даже одного составного (вложенного) запроса, он не будет ресурсоемким в силу простоты и небольшого количества записей в таблице корзины. Ну а при не регистрированном клиенте все еше проще. В общем, я бы написал отдельный код или функцию для получения списка productID в корзине. Понятно, что при оформлении заказа количество SQL-запросов не особенно и критично, но просто для красоты процесса.
  • 0
http://cpu.badisoft.ru (тестовый сайт), http://badisoft.ru (модули)

#7 Robby

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

  • Assistent vsupport.club
  • PipPipPip
  • 162 сообщений
Репутация: 75
Продвинутый

Отправлено 23 May 2016 - 09:13 PM

Такое поведение было описано на официальном форуме. Вот, нашел это сообщение (датировано 2009 годом), в нем автор приводит и решение проблемы. Похоже пришло время это проверить :) .
  • 0

#8 badisoft

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

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

Отправлено 23 May 2016 - 09:18 PM

Максим » 23 дек 2009, 15:27 Спасибо, программисты сегодня посмотрят, я потом отпишу что скажут. Но что-то я не уверен что в скрипте последней версии есть такие проблемы.

И это все, что нужно знать об официальной поддержке ShopCMS.
  • 0
http://cpu.badisoft.ru (тестовый сайт), http://badisoft.ru (модули)