Специалисты по Drupal, прошу вашей помощи.
Поднимаю магазин на Ubercart. Остатки товара на складе отслеживаются модулем uc_stock.
При достижении определённого уровня запасов, на мыло админу шлётся письмо с предупреждением. Это реализовано следующей функцией в uc_stock.module:
$token_filters = array('global' => NULL, 'order' => $order, 'stock' => $stock);
$account = user_load(array('uid' => $order));
$to = variable_get('uc_stock_threshold_notification_recipients', variable_get('uc_store_email', ini_get('sendmail_from')));
$to = explode(',', $to);
$from = uc_store_email_from();
$subject = variable_get('uc_stock_threshold_notification_subject', uc_get_message('uc_stock_threshold_notification_subject'));
$subject = token_replace_multiple($subject, $token_filters);
$body = variable_get('uc_stock_threshold_notification_message', uc_get_message('uc_stock_threshold_notification_message'));
$body = token_replace_multiple($body, $token_filters);
// Send to each recipient.
foreach ($to as $email) {
$sent = drupal_mail('uc_stock', 'threshold', $email, uc_store_mail_recipient_language($email), array('body' => $body, 'subject' => $subject), $from);
if (!$sent['result']) {
watchdog('uc_stock', 'Attempt to e-mail email concerning stock level on sku sku failed.', array('email' => $email, 'sku' => $stock->sku), WATCHDOG_ERROR);
}
}
}
при достижении порогового значения запаса, модуль шлёт письмо
if (variable_get('uc_stock_threshold_notification', FALSE) && $stock->stock <= $stock->threshold) {
_uc_stock_send_mail($order, $stock);
}
Есть задача - при достижении нулевого уровня запасов товара, снимать его с публикации (нет товара - и незачем ему на складе валяться). Долго я думал, как же мне это замутить и спрашивал даже - http://www.drupal.ru/node/38115 . Но решения так и не нашлось.
Вот меня осенило, а что если с вызовом функции отправки предупредительного письма, вызвать функцию node_unpublish_action. Она определена в modules/node/node.module
Попробовал вот так:
if (variable_get('uc_stock_threshold_notification', FALSE) && $stock->stock <= $stock->threshold) {
_uc_stock_send_mail($order, $stock);
node_unpublish_action(&$node, $context = array());
}
не получилось. Товар так и остался опубликованным.
Попробовал вынести в отдельную проверку:
Тоже лыжи не едут.
Что делаю не так?
РЕШЕНО (правда немного нетрадиционно, но сроки поджимают)
В файле uc_stock.module в проверке // Should we notify? вставить sql запрос
db_query('UPDATE {node} SET status = 0 WHERE nid = %d', $product->nid);
Пусть идеологически неправильно, зато работает.
Комментарии
Может идеологически неправильно, но я бы простым sql запросом снял с публикации:
Спасибо за подсказку.
Но всё равно торможу.
Попробовал применить Ваш код и в отдельной проверке и вставлял прямо в функцию отправки письма, указанную в топовом посте.
Не получается. status ноды ни в какую меняться не желает. Письмо отсылается исправно.
а %d вроде бы надо заключать в одинарные кавычки - '%d'. или нет?
db_query("UPDATE {node} SET status = 0 WHERE nid = %d", $node->nid);
методом проб и ошибок докопался до следующей проблемы:
$node->nid
почему-то не передаёт в выражение WHERE номер ноды.А если поставить номер ноды вручную (ну просто для проверки например 116)
db_query('UPDATE {node} SET status = 0 WHERE nid = 116');
то всё работает на ура.
И письмо уходит о низком складском запасе и нода 116 снимается с публикации.
Уже час мучаюсь, не могу понять, почему
$node->nid
не работает как надо...Помогите. В чём грабли то?
Всё. Допёр сам.
Надо в запросе писать не
$node->nid
, а$product->nid
wolfXXXL - огромное спасибо за подсказку.
Правильней было бы снимать товар который оплатили, так как если товар не оплачен, то он может быть возращен обратно в каталог.
Правильно было бы вообще оставлять товар как есть, а просто дисаблить кнопку заказа и писать "Этот товар раскупили, оставьте ваше мыло, мы скажем когда снова будет" . Для Уберкарта 1 видел когда то такой модуль
Снимать товар - это терять позиции в серпе по его ключевику
А не снимать - побьют пользователи за захламление.
Конечно смотря что продавать.
Не видел никогда ни одного, даже самого крутого инет-магазина, который бы торговал 100% тем, что реально в наличии.
Формулировки разные надо. Не "Нет в наличии", а "Товар уже в дороге"
Посмотри molotok.ru
Товар уже в дороге - это интимная информация и показывать надо в статусе, а не всем подряд пользователям сайта.:)
Сео сеом, а теперь представь, что товары в единичных экземплярах...и все время новые. И получается что на каждой странице примерно 80 процентов нет в наличии. Анод так под 100000 и все время растет количество.
ага, чтоб пользователь повесился пока будет ждать пока этот модуль просканирует на странице все 40товаров и выведит свое заключение.;)
Ветер, я сам продаю онлайн, я знаю о чём говорю, убеждать меня не надо Пользователи нормально относятся к тому, что возможно, товара нет в наличии. Посчитай, сколько ты потратишь на оформление страницы товара, чтобы его потом просто так убирать
Я никого не убеждаю. Просто констатирую. И не надо говорить за пользователей. Вы делали опрос?
Кто сказал что я трачу свое время?
Ага, и 1000 пользователей висит в онлайне
Сколько висит совершенно не важно. Речь идет совершенно о другом.
Спасибо за патч, то, что нужно!
теперь пытаюсь другую проблему победить. Есть товар у которого атрибут размер с опциями S,M,L,XL,XXL... Соответственно, для конкретной опции указан остаток, как сделать чтобы при заказе товара проверялся остаток и, если < порога, то убирать данную опцию?
Возможно оффтоп и не в тему, но может кто подскажет, как реализовать то же самое в commerce?
Drupal 7, как снять с публикации ноды с товарами в commerce, если commerce_stock=0 ???
p.s.: Возможно позже создам новую тему, если сам не разберусь, т.к. интересует, как вывести commerce_stock в список общих полей, чтобы работать с rules и views по нодам...
Я недавно начал знакомиться с друпалом, по этому прошу сильно не пинать.
Подскажите пожалуйста, куда копать и что искать хотябы...
Очень нужное дополнение, если товары продаются в единичном экземпляре. В общем используя данное исправление возникает еще одна проблема:
Если в одно и тоже время 2 пользователя добавили один и тот же товар в свою корзину, то в итоге оба смогут совершить оплату (соответственно - покупку) одного товара. Что не есть хорошо. Для исправления данной проблемы, в дополнении к вышеприведенному исправлению кода предлагаю на обсуждение свое дополнительное исправление файла uc_cart.pages.inc из модуля uc_cart (так же - идеологически не верное но зато эффективное )
В вышеозначенном файле поменять функцию uc_cart_checkout_review_form_submit
заменив ее на такую (дополненная)
PS
Работать , конечно, будет только при условии возможности добавления товара в корзину авторизованного юзера, так как удаление из корзины проданного товара происходит по uid. Для работы и с анонимами, код нужно допиливать
<?php function uc_cart_checkout_review_form_submit($form, &$form_state) {
$msg_type = 'status';
// Stop invoking the hooks if there was an error.
// Invoke hook_order($op = 'submit') to test to make sure the order can
// be completed... used for auto payment in uc_credit.module.
$order = uc_order_load($_SESSION['cart_order']);
$error = FALSE;
// Мой код
$sss=$order->products;
// print_r($sss);
foreach ($sss as $key => $value)
{
$mask = db_fetch_object(db_query("SELECT * FROM {node} WHERE nid = %d LIMIT 0,1", $sss[$key]->nid ));
if($mask->status==0)
{
$rem[] = array ($sss[$key]->title, $sss[$key]->nid);
}
}
if(isset($rem))
{
$error = TRUE;
$msg_type = 'error';
global $user;
foreach ($rem as $key => $value)
{
db_query("DELETE FROM {uc_cart_products} WHERE cart_id = %d AND nid = %d", $user->uid, $rem[$key][1]);
drupal_set_message('К сожалению пункт:<strong> '. $rem[$key][0] . '</strong> был продан раньше. Он удален из вашей корзины.', $msg_type);
}
drupal_set_message('Ваша корзина актуализирована. Повторите оплату с новой итоговой стоимостью или добавьте активные пункты. Спасибо.', $msg_type);
$_SESSION['do_review'] = TRUE;
$form_state['redirect'] = 'cart';
}
// print_r($order);
//print_r($mask);break;
// Invoke it on a per-module basis instead of all at once.
// конец моего кода (не учитывая следующий else-блок)
else{
foreach (module_list() as $module) {
$function = $module .'_order';
if (function_exists($function)) {
// $order must be passed by reference.
$result = $function('submit', $order, NULL);
if ($result[0]['pass'] === FALSE) {
$error = TRUE;
$msg_type = 'error';
}
if (!empty($result[0]['message'])) {
drupal_set_message($result[0]['message'], $msg_type);
}
if ($error) {
break;
}
}
}
if (
$error) {$_SESSION['do_review'] = TRUE;
$form_state['redirect'] = 'cart/checkout/review';
}
else {
$_SESSION['do_complete'] = TRUE;
$form_state['redirect'] = 'cart/checkout/complete';
}
}
}?>