Drupal 7: Создание технической поддержки (тикеты).

Создаем систему поддержки на Drupal 7.

19.04.2013
30 комментариев
9 мин.

Хотели сделать службу тех поддержки на Drupal-сайте, но не знали с чего начать? Этот гайд будет вам в помощь. В ходе данного гайда мы создам обычную службу технической поддержки на сайте.

Данное руководство я пишу, прежде всего, для drupal-пользователей средней руки. А это значит, вы должны понимать что такое Views, Rules и прочие популярные модули, или догадаться в ходе действий, так как рассказывать особо я о них не буду. Говоря еще понятнее, если вы только вчера поставили друпал — даже не пробуйте. Также буду рассказывать по английской версии системы, ибо:

  1. Просто-напросто лень переводить ядро и модули;
  2. Я всегда делаю на англ. языке, ибо проще во всем, хоть я и не владею свободно английским;
  3. Смотрю на созданные мною сайты, но с русской админкой, меня это сбивает с толку, ибо перевод местами просто «хер поймешь».

Подготовка

Еще не потеряли уверенность? Тогда запасаемся модулями: Views (ctools), Rules(Entity), Token, также по желанию можете поставить Admin Menu. Все это дело включаем и поехали.

Я набросал небольшую схему, на основе которой мы будем все создавать.

График нашего тикета.

Как вы можете увидеть из графика, сам тикет будет типом содержимого, у тикета будет три параметра: статус, категория и приоритет. Все параметры мы выносим в отдельные словари, где будут необходимые нам термины.

Возможно у кого-то назреет вопрос, а почему бы это все не выносить в отдельные словари, а тупо создать поле-выборку и туда вбить значения, все будет в одном месте. Такой подход имеет место быть, но что если, допустим, вам надо будет поменять все категории, или часть из них? Вот тут и всплывут грабли данного метода. Управлять всем этим на уровне словарей намного проще, и как по мне, намного логичнее.

Создаем словари

Я выделил три словаря: категория, статус и приоритет. Поэтому заходим в таксономию и создаем их, попутно забиваем некоторыми терминами. Также дадим им более адекватные названия:

  • Тикет: Категории (ticket_category): «Техническая поддержка», «Отдел продаж».
  • Тикет: Приоритеты (ticket_priority): «Обычный», «Высокий», «Критический».
  • Тикет: Статусы (ticket_status): «Открыт», «Закрыт».

Тут никаких сложностей в принципе быть не должно.

Создаем ноду — тикет

Заходим в типы содержимого, и нажимаем создать новый. Указываем имя «Тикет» (ticket — машинное), снимаем галочку «Promoted to front page», в разделе комментариев снимаем галочку «Allow comment title», жмем «Save and Add fields» и приступаем к добавлению полей:

Статус (ticket_status) типа «Term reference» - «Select list». Связываем со словарем «Тикет: статусы». Устанавливаем галочку «Required field». По умолчанию: «Открыт».

**Категория (ticket_category) **типа «Term reference» - «Select list». Связываем со словарем «Тикет: категории». Устанавливаем галочку «Required field». По умолчанию: «Техническая поддержка».

Приоритет (ticket_priority) типа «Term reference» - «Select list». Связываем со словарем «Тикет: приоритеты». Устанавливаем галочку «Required field». По умолчанию: «Обычный».

Получаем примерное следующее:

Поля материала - тикет.

На этом настройка ноды закончена, идем дальше.

Создаем формы для ответов (переписки)

На тикеты надо будет отвечать, и совершенно очевидно что у тикета также должна быть возможность менять статус, категорию и приоритет в ходе переписки. Как же мы это все прикрутим? Все достаточно просто, мы для этого будем использовать стандартные комментарии ноды.

Для начала перейдем на вкладку полей комментариев ноды «Тикет».

Поля комментариев.

У нас на данный момент всего одно поле «Comment», которое является текстовым полем самого комментария. Давайте заменим слово Comment на «Ответ», чтобы было логичнее и пойдем дальше.

А дальше нам необходимо дать возможность смены статуса, приоритета и категории тикета. Для этого мы не будем опять создавать поля, мы их создали в ноде, поэтому их же и будем использовать.

Поэтому добавляем копии полей, которые мы создавали на предыдущем этапе. Только в этот раз мы не ставим «Required field», не заполняем «Default value», а просто сохраняем добавленную копию поля. Если не ясно, то это убирает проблему, когда каждый раз при ответе приходилось бы указывать данные параметры. Теперь они меняются только по необходимости.

Список полей комментариев.

На этом фундамент тех. поддержки заложен, но ни о какой функциональности и речи быть не может.

Создаем Rules'ы

Сейчас мы добавим обработчики, которые помогут нам менять статус тикета, при смене его во время ответа (при комментариовании), так как сейчас это ни на что не влияет, ну и прочие мелочи. И тут-то начинаются финты ушами, ибо сходу такие рулсы не запилить.

Итак, первое что нам нужно, это убрать лишнее поле - «Заголовок\title». Его нельзя удалить у ноды, а его необходимость в тикете очень сомнительна, и это нужно как-то решать. У данного поля нет никаких настроек, мы даже не можем его сделать необязательным и это как раз вызывает потребность в его отключении. Мы поступим проще, мы будем после создания тикета в него закидывать номер тикета, который будет равняться NID, а само поле мы тупо через CSS уберем, присвоив ему display: none.

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

Шаг 1. Создаем новое правило (Rule) и называем его «Тикет: Смена заголовка тикета (ticket_change_title)».

Шаг 2. Все также при создании, в поле выбора на что среагирует правило, выбираем «After saving new content» и жмем «Save».

Шаг 3. Добавляем новый «Condition» - «Content is of type» и в разделе «Content types» выбираем «Тикет», сохраняем.

Шаг 4. Добавляем Action «Set a data value» и в «Data slector» указываем «node:title». Жмем продолжить и на следующем этапе в поле «Value» вводим «#[node:nid]» и сохраняем.

Шаг 5. Жмем «Save changes» и наше правило готово.

Правило изменение заголовка тикета.

Тем самым, после создания тикета, ему автоматически присвоится название #NID.

Смена статуса\\приоритета\\категории

Это самое интересное в данном разделе, так как все мозги вскипели пока смог провернуть данный финт. Я расскажу на примере «Смена статуса», а остальные два сделаете точно также, только с очевидными для них изменениями.

Шаг 1. Создаем правило и называем его «Тикет: Смена статуса (ticket_change_status)». Устанавливаем реакцию на событие «After saving a new comment».

Шаг 2. Добавляем новый «Condition» - «Content is of type» и выбираем «Тикет».

Шаг 3. Добавляем еще один «Condition» - «Entity has field». В поле «Data selector» указываем «comment», а в «Field» выбираем «field_ticket_status» (или то, в зависимости что добавляете, например проритет).

Шаг 4. Добавляем последний «Condition» - «Data value is empty». В «Data selector» указываем «comment:field-ticket-status», а также устанавливаем галочку «Negate» и сохраняем.

Шаг 5. Добавляем «Action» - «Set a data value». В «Data selector» указываем «comment:node:field-ticket-status» и жмем продолжить. На следующем этапе в «Data selector» должно стоять «comment:field-ticket-status» само по себе, но если не стоит то добавьте. И сохраняем.

Правило изменение статуса.

Теперь тоже самое проделайте с приоритетами и категориями. Разница будет лишь в выборе полей.

После того как сделали для остальных двух, у вас должно получиться 4 правила. Вы также можете добавить по принципу и подобию оповещение о новых ответах на почту и т. д. В общем Rules в ваших руках ;)

Исправление ошибок

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

Закрываем тикеты от сторонних глаз

Итак, что мы будем делать? Ситуация достаточно нестандартная для встроенных прав, хотя она достаточно актуальная. Почему такие права не ввели в ядро, да кто его знает. Но проблема есть и решений ей куча с горкой, есть модули, есть кастомные решения. Я пробовал модуль «Content access» - забудьте сразу. Ужасный модуль, вываливает кучу ероров и чтобы их устранить нужно ставить dev-ветку, которая хоть и не еррорит, зато ломает Views и прочие модули на ctools. В общем какой-то мутный модуль, и достаточно громоздкий для нашего решения. Если у вас есть свой модуль на примете — используйте его, я же буду делать кастомное решение.

Для создания кастомного решения нам придется вызвать hook_node_access(). Данный хук нужно вызывать из модуля, который нам придется сделать (это не страшно). Я не собираюсь учить делать модули в данной статье, кто знает, берем и используем код:

hook_node_access()
    /**
     *  Применяем hook_node_access().
     *
     *  Блокирует доступ к ноде 'ticket' всем пользователям, кроме автора и админа.
    */
    function hook_node_access($node, $op, $account) {
      if (is_object($node)) {
        if (($node->type == 'ticket')  && (($op == 'view') || ($op == 'update'))) {
          if ($account->uid == $node->uid) {
            return NODE_ACCESS_ALLOW;
          }
          else {
            return NODE_ACCESS_DENY;
          }
        }
      }
    
      return NODE_ACCESS_IGNORE;
    }

Кто не знает, качайте заготовку> и не забываем включить.

Устраняем проблему с заголовком тикета

Тут все также просто, мы укажем пустое значение по умолчанию, которое позволит пропустить заполнение данного поля, а затем Rules подхватит и сменит на нужный нам заголовок. Для этого используем код:

hook_form_FORM_ID_alter()
    /**
     *  Применяем hook_form_ID_alter().
     *
     *  Ставим полю title ноды типа 'ticket' пустое значение.
     *  Также устанавливаем полю title новый class - 'hidden'.
     */
    function hook_form_ticket_node_form_alter(&$form, &$form_state, $form_id) {
      $form['title'] = array(
        '#type' => 'textfield',
        '#maxlength' => 255,
        '#weight' => -5,
        '#required' => FALSE,
        '#default_value' => '',
        '#attributes' => array(
          'class' => array(
            'hidden',
          ),
        ),
      );
    }

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

.hidden {
  display: none;
}

Проверка

Вы уже можете зайти и проверить как работают тикеты.

Результат тикета.

Это выглядит убого, но это работает. Дело осталось за малым, все это темизировать, чтобы было ясно что к чему, а также создать представления для отслеживания данных тикетов.

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

Создание вьюх с тикетами

Начнем с банальной доработки — мы структурируем все тикеты. Тут выходит на помощь — views. Если еще не включили\установили — самое время начать.

Итак, создаем новую вьюху и называем её «Техническая поддержка (technical_support)», снимаем галочку «Create a page» и жмем «Continue & edit».

Теперь будем все делать пошагово.

Все тикеты пользователя

Шаг 1. Жмем «Add» и выбираем «Page».

Шаг 2. В «Display name» и «Title» пишем «Техническая поддержка». Можете «Список тикетов» или как душе угодно.

Шаг 3. «Format» выбираем «Table».

Шаг 4. Полю «Content: Title» ставим галочку «Create a label» и пишем в поле «Label» - «ID».

Шаг 5. Добавляем новое поле «Field: Категория», в типе форматирования выбираем «Plain text», сохраняем.

Шаг 6. Добавляем новое поле «Field: Приоритет», в типе форматирования выбираем «Plain text», сохраняем.

Шаг 7. Добавляем новое поле «Field: Статус», в типе форматирования выбираем «Plain text», сохраняем.

Шаг 8. Добавляем новое поле «Content: New comments», ставим галочку «Exclude from display», в префикс пишем «(новых », а в суффикс «)», сохраняем.

Шаг 9. Добавляем новое поле «Content: Comment count», в «Label» пишем «Ответов». Затем открываем «Rewrite results» и ставим галочку «Rewrite the output of this field». Далее в текстовое поле вставляем «[comment_count] [new_comments]» и сохраняем.

Шаг 10. В «Filter criteria» добавляем правило «Content: Type», выбираем «Тикет», сохраняем.

Шаг 11. В «Page settings → Path» пишем «support».

Шаг 12. В «Header» добавляем «Global: Text area» и пишем

<a href="/node/add/ticket">Создать новый Тикет</a>

<h2>Ваши обращения:</h2>

Шаг 13. В «Pager» выбираем «Display all items».

Шаг 14. В «Contextual filters» добавляем фильтрацию по «Content: Author uid», указываем «Provide default value» и в поле тип выбираем «User ID from logged in user», сохраняем.

Шаг 15. В «No results behavior» добавляем «Global: Text area» и пишем:

<h2>Вы не создавали ни одного обращения в службу технической поддержки. Вы можете создать новый тикет нажав на кнопку ниже.</h2>

<a href="/node/add/ticket">Создать новый Тикет</a>

Шаг 16. Сохраняем представление.

Тикеты пользователя.

Создание административной вьюхи

Теперь создадим представление через которое можно управлять тикетами. Не забывайте везде ставить в поле «For» (самое верхнее) значение «This page (override)».

Шаг 1. Жмем «Add» и выбираем «Page».

Шаг 2. «Display name» и «Title» присваиваем значение «Техническая подддержка (Администрирование)», или как вам надо, и не забываем указать что значение только для данной страницы.

Шаг 3. В «Filter criteria» добавляем «Field: Категория», затем выбираем «Dropdown», далее ставим галочку «Expose this filter ...», «Label» правим на просто «Категория» и сохраняем.

Шаг 4. В «Filter criteria» добавляем «Field: Приоритет», затем выбираем «Dropdown», далее ставим галочку «Expose this filter ...», «Label» правим на просто «Приоритет» и сохраняем.

Шаг 5. В «Filter criteria» добавляем «Field: Статус», затем выбираем «Dropdown», далее ставим галочку «Expose this filter ...», «Label» правим на просто «Статус» и сохраняем.

Шаг 6. В «Page settings → Path» указываем «support/admin».

Шаг 7. В «Access» указываем «Role → Administrator».

Шаг 8. Удаляем «Contextual filter», также не забыва предварительно его перезаписать для данной страницы.

Шаг 9. Сохраняем представление.

Если вы не проспали где-то с перезаписью, то все получится.

Разрешите в правах пользователям создавать тикеты, а затем создайте обычного юзера и проверьте как все работает.

Примерно получится так для юзера:

Пользователь поддержки.
Администратор.

Теперь если администратор ответит на тикет пользователя (#2), в его списке это будет отражено.

Новый ответ.

Вот так можно создать несложную техническую поддержку на сайте.

Дело осталось за малым, все это добро темизировать. Но учить я вас, разумеется, этому не стану. Я просто создам пример, а вы уже сами ковыраяйте ;)

Включив тему Corolla и немного поговнокодив, я привел сообщения к такому виду:

Результат.
Прикрепленные файлы
Модуль блокировки тикетов — ticket_access.zip, 1.32 КБ
Результат выполнения — drupaldev.20130419_044448.tar.gz, 6.38 МБ
Drupal
Drupal 7
View
Rules
Token

Комментарии

Niklan   вс, 28/04/2013 - 22:13

Feature готова - http://niklan.net/blog/32

Внизу статьи ссылка на неё. Всеравно поработать придется, в частности убрать title как обязательное поле.

Sky   сб, 29/06/2013 - 20:20

Немогу понять как запустить выложенный вами сайт. База данных запустилась все нормально. Сайт не идет. Скажите пожалуйста как его запустить. А статья хорошая. Поднимаю сат заказа услуг на основе вашей идеи.

Дмитрий   пн, 08/07/2013 - 21:52

А через что лучше реализовать оповещение пользователей об изменении "статуса" тикета?Или получения комментария?

Денис   вс, 05/04/2015 - 13:47

А можно поподробней, как при изменении статуса тикета, выводилось сообщение только тому пользователю который создал этот тикет ?

Как сделать блок на сайте, котрый бы отображал сообщения по тикетам, что добавился комментарий или изменился статус тикета, а каую сторону копать ?

Гость   вт, 16/07/2013 - 14:10

При установке правил (Rules) в "Смена статуса\приоритета\категории" в шаге №4 в "Data selector" нужно указать: comment:node:field-tiket-status

«comment:field-ticket-status» - там такого нет, ведь это к ноде привязывается

Александр   ср, 14/08/2013 - 12:58

Подскажите,  а как можно выделить другим цветом тикеты с приоритетом Высокий/Низкий ?

Niklan   ср, 14/08/2013 - 13:01

Темизировать вывод. Добавить соответствующие классы на ноды или тизеры, а их уже цветом через CSS.

AP   чт, 17/10/2013 - 11:00

Та же ерунда node: с различными модификациями список исчерпывается...

Niklan   чт, 17/10/2013 - 12:01

Подучите темизацию. Все легко темизируется. Хоть для каждого статуса свой собственный вид. Я в двух словах не объясню.

Александр   ср, 14/08/2013 - 17:19

Ещё вопросик, а можно ли как то сделать запрет на комментирование при термине "Закрыто" словаря "Статус"?

Niklan   ср, 14/08/2013 - 19:49

Можно. Сделать рулес, и когда статус меняется на закрыто, выключать возможность комментирование ноды.

Александр   чт, 15/08/2013 - 11:57

А можно чуток по подробней? Ибо чтото мозг не может понять. Не могу найти где по ставить запрет и не знаю что ставить в Condition.

Сергей   сб, 17/08/2013 - 23:27

Спасибо за инструкцию, все очень подробно и понятно изложено!

Ирина   пт, 09/05/2014 - 21:32

Здравствуйте! Решила реализовать службу технической поддержки, но появилось много вопросов. Подскажите, пожалуйста, как в необходимый блок вставить кнопку, при нажатии на которую в поле "активен" этого пользователя значение устанавливается на "активен" и разрешается назначение этому пользователю заявок(думаю это сделать через термины таксономии),а при повторном нажатии на кнопку-значение меняется на "неактивен" и заявки назначать этому пользователю становится недоступным. Пыталась сделать через Rules, но т.к. php для меня пока что темный лес, все безрезультатно. Была бы очень благодарна за помощь!

Сергей   пн, 01/09/2014 - 17:17

Дополнение к:
>> В «Data selector» указываем «comment:node:field-ticket-status» и жмем продолжить.
Вы не сможете выбрать этот селектор, если пропустите Шаг 2:
>>Шаг 2. Добавляем новый «Condition» - «Content is of type» и выбираем «Тикет».
личный опыт, почему-то я решил что достаточно ограничения в Events (в более новой версии Rules можно выбрать тип ноды сразу же в Events секции).

Вячеслав   сб, 27/09/2014 - 17:10

Добрый день. Спасибо за инструкцию. Пробую организовать нечто похожее. Не получилось провернуть хак с заголовком ноды и пришлось искать варианты. Наткнулся на отличный крохотный модуль auto_nodetitle, который отвечает именно за это. Думаю, кому нибудь пригодится.

дмитрий   вс, 14/12/2014 - 00:43

Поставил Ваш сайт из приложения. Подскажите какой логин и пароль администратора?

Niklan   вс, 14/12/2014 - 07:43

admin\admin
admin\root
root\root

Что-то подойдет или сбросьте пароль просто.
 

Алексей   ср, 25/03/2015 - 00:23

Здравствуйте! Подскажите пожалуйста, можно ли сделать следующие этапность в тикетах, т.е. делается запрос и администратор 1 отвечает и меняет на статус " передано в тех. службу", а админ 2 отвечает на этот тикет и меняет статус "Отвечено" суть в том что админ 1 не должен иметь доступ до типа статуса админа 2 и наоборот. Реально это сделатьи с помощью чего? спасибо

ALFAQ   пт, 21/08/2015 - 13:22

Не подскажете как создать Rules просто после сохранения материала отметить другой термин. Например после редактирования автором своей ноды установить поле термина в Ожидает модерации

Ebrefebre   пт, 30/04/2021 - 07:56

Привет! У меня 8 друпал, возможно в нём что-то реализовано по-другому, но: у меня при создании ноды тикет не позволяет выбрать словарь таксономии. Есть выбор словаря из модуля Forums, там их два, а только что созданные словари в списке отсутствуют. Я точно делаю что-то не так, прошу, направьте меня

Сергей   вт, 20/09/2022 - 08:43

Существует возможность изменить статус заявки из административной вьюхи, не редактируя саму ноду?