[РЕШЕНО] Снятие товара с публикации при достижении нулевого остатка на складе

Главные вкладки

Аватар пользователя sergey-v-fedorov sergey-v-fedorov 29 января 2010 в 22:31

Специалисты по Drupal, прошу вашей помощи.

Поднимаю магазин на Ubercart. Остатки товара на складе отслеживаются модулем uc_stock.
При достижении определённого уровня запасов, на мыло админу шлётся письмо с предупреждением. Это реализовано следующей функцией в uc_stock.module:

function _uc_stock_send_mail($order, $stock) {
  $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);
    }
  }
}

при достижении порогового значения запаса, модуль шлёт письмо

// Should we notify?
  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

Попробовал вот так:

// Should we notify?
  if (variable_get('uc_stock_threshold_notification', FALSE) && $stock->stock <= $stock->threshold) {
    _uc_stock_send_mail($order, $stock);
    node_unpublish_action(&$node, $context = array());
  }

не получилось. Товар так и остался опубликованным.

Попробовал вынести в отдельную проверку:

  if ($stock->stock <= 0) {
  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);

Пусть идеологически неправильно, зато работает.

Комментарии

Аватар пользователя sergey-v-fedorov sergey-v-fedorov 30 января 2010 в 17:33

Спасибо за подсказку.
Но всё равно торможу.
Попробовал применить Ваш код и в отдельной проверке и вставлял прямо в функцию отправки письма, указанную в топовом посте.

Не получается. status ноды ни в какую меняться не желает. Письмо отсылается исправно.

а %d вроде бы надо заключать в одинарные кавычки - '%d'. или нет?

Аватар пользователя sergey-v-fedorov sergey-v-fedorov 30 января 2010 в 18:34

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 не работает как надо...

Помогите. В чём грабли то?

Аватар пользователя Ветер Ветер 25 октября 2010 в 1:29

Правильней было бы снимать товар который оплатили, так как если товар не оплачен, то он может быть возращен обратно в каталог.

Аватар пользователя volocuga@drupal.org volocuga@drupal.org 25 октября 2010 в 1:41

Правильно было бы вообще оставлять товар как есть, а просто дисаблить кнопку заказа и писать "Этот товар раскупили, оставьте ваше мыло, мы скажем когда снова будет" . Для Уберкарта 1 видел когда то такой модуль

Снимать товар - это терять позиции в серпе по его ключевику

Аватар пользователя volocuga@drupal.org volocuga@drupal.org 25 октября 2010 в 1:51

Не видел никогда ни одного, даже самого крутого инет-магазина, который бы торговал 100% тем, что реально в наличии.

Формулировки разные надо. Не "Нет в наличии", а "Товар уже в дороге"

Аватар пользователя Ветер Ветер 25 октября 2010 в 15:23

Посмотри molotok.ru

Товар уже в дороге - это интимная информация и показывать надо в статусе, а не всем подряд пользователям сайта.:)

Сео сеом, а теперь представь, что товары в единичных экземплярах...и все время новые. И получается что на каждой странице примерно 80 процентов нет в наличии. Анод так под 100000 и все время растет количество.

Аватар пользователя Serge66 Serge66 25 октября 2010 в 4:40

"<a href="mailto:volocuga@drupal.org">volocuga@drupal.org</a>" wrote:
Правильно было бы вообще оставлять товар как есть, а просто дисаблить кнопку заказа и писать "Этот товар раскупили, оставьте ваше мыло, мы скажем когда снова будет" . Для Уберкарта 1 видел когда то такой модуль
out of stock

Аватар пользователя Ветер Ветер 25 октября 2010 в 15:12

ага, чтоб пользователь повесился пока будет ждать пока этот модуль просканирует на странице все 40товаров и выведит свое заключение.;)

Аватар пользователя volocuga@drupal.org volocuga@drupal.org 25 октября 2010 в 15:27

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

Аватар пользователя Ветер Ветер 25 октября 2010 в 15:53

Я никого не убеждаю. Просто констатирую. И не надо говорить за пользователей. Вы делали опрос?
Кто сказал что я трачу свое время? Smile

Аватар пользователя maxneb maxneb 27 марта 2011 в 18:14

Спасибо за патч, то, что нужно!
теперь пытаюсь другую проблему победить. Есть товар у которого атрибут размер с опциями S,M,L,XL,XXL... Соответственно, для конкретной опции указан остаток, как сделать чтобы при заказе товара проверялся остаток и, если < порога, то убирать данную опцию?

Аватар пользователя darker darker 23 сентября 2012 в 14:42

Возможно оффтоп и не в тему, но может кто подскажет, как реализовать то же самое в commerce?
Drupal 7, как снять с публикации ноды с товарами в commerce, если commerce_stock=0 ???

p.s.: Возможно позже создам новую тему, если сам не разберусь, т.к. интересует, как вывести commerce_stock в список общих полей, чтобы работать с rules и views по нодам...

Я недавно начал знакомиться с друпалом, по этому прошу сильно не пинать.
Подскажите пожалуйста, куда копать и что искать хотябы...

Аватар пользователя t-m-p t-m-p 6 февраля 2013 в 17:19

Очень нужное дополнение, если товары продаются в единичном экземпляре. В общем используя данное исправление возникает еще одна проблема:
Если в одно и тоже время 2 пользователя добавили один и тот же товар в свою корзину, то в итоге оба смогут совершить оплату (соответственно - покупку) одного товара. Что не есть хорошо. Для исправления данной проблемы, в дополнении к вышеприведенному исправлению кода предлагаю на обсуждение свое дополнительное исправление файла uc_cart.pages.inc из модуля uc_cart (так же - идеологически не верное но зато эффективное )

В вышеозначенном файле поменять функцию uc_cart_checkout_review_form_submit

заменив ее на такую (дополненная)

PS
Работать , конечно, будет только при условии возможности добавления товара в корзину авторизованного юзера, так как удаление из корзины проданного товара происходит по uid. Для работы и с анонимами, код нужно допиливать Smile

<?php function uc_cart_checkout_review_form_submit($form, &$form_state) {
  
// 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'$orderNULL);

      

$msg_type 'status';
      if (
$result[0]['pass'] === FALSE) {
        
$error TRUE;
        
$msg_type 'error';
      }
      if (!empty(
$result[0]['message'])) {
        
drupal_set_message($result[0]['message'], $msg_type);
      }

      

// Stop invoking the hooks if there was an error.
      
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';
  }
}
}
?>