Расширение логики модулей или Logic Hooks. Часть 2

В предыдущей статье мы рассмотрели теорию создания logic hooks. Сегодня разберем реальный практический пример использования данных «логических крюков» :smile: . А заодно и увидим механизм автоматического создания relationship (связей) между модулями.

Задача.
У одной из компаний, для которой мы настраивали SugarCRM, большинство контрагентов состоит из одного контакта. Такая ситуация, думаю, присуща не только им. Так вот представьте теперь, как неудобно при создании сделки каждый раз, помимо контрагента, выбирать в сделке в субпанели контакт, который к тому же один. Решили: если контакт у контрагента один, то автоматически добавлять связь со сделкой. Если нет, то тогда менеджер добавляет связь вручную (вы можете легко исправить на добавление связи со всеми контактами, только первым и т.д.). Как видим, для решения этой задачи нам необходимо изменить логику модуля сделки. А именно – добавить действие после сохранения записи. Напомню, что это событие after_save.

Как мы уже знаем из первой части (теоретической), надо создать файл с описанием «хука» по такому пути:

custom/modules/Opportunities/logic_hooks.php

Добавим следующее содержимое:

<?php
$hook_version = 1;
$hook_array = Array();
$hook_array['after_save'] = Array();
$hook_array['after_save'][] = Array(101, 'Проверка и добавление авто связи с контактом', 'custom/Extension/modules/Opportunities/Ext/CustomLogicHook.php','OpportunityCustomLogicHook', 'afterSaveRelationshipToContact');
?>

Если же у вас уже есть такой файл (многие сторонние модули могли уже создать файлы с определением logic hooks), то вам необходимо только добавить описание самого хука. Как видно из описания, после создания сделки вызывается функция: afterSaveRelationshipToContact находящаяся в файле по пути custom/Extension/modules/Opportunities/Ext/CustomLogicHook.php.

Содержимое этого файла:

<?php
class OpportunityCustomLogicHook extends SugarBean
{
  function afterSaveRelationshipToContact(SugarBean $bean, $event, $arguments)
  {
    $related_contacts = $bean->get_related_list(new Contact(),"contacts");
    if ($related_contacts)
    {
      if (isset($related_contacts['list']) and count($related_contacts['list']) == 0)
      {
        $related_accounts = $bean->get_related_list(new Account(),"accounts");
        if (isset($related_accounts['list']) and count($related_accounts['list']) == 1)
        {
          $account_bean = $related_accounts['list'][0];
          $account_bean->load_relationship('contacts');
          $contact_list = $account_bean->contacts->getBeans(loadBean('Contacts'));
          if (is_array($contact_list) and count($contact_list) == 1)
          {
            $contact = $contact_list[0];
            $bean->contacts->add($contact->id);
          }
        }
        else
          return;
      }
    }
  }
}
?>

Прокомментирую подробно код.

В данной функции мы получаем bean класс сделки. Так что дальше в коде $bean — это класс Opportunity ().

$related_contacts = $bean->get_related_list (new Contact (),"contacts"); — получаем спискок всех контактов, связанных со сделкой.

if (isset ($related_contacts['list']) and count ($related_contacts['list']) == 0); — если связь с модулем контактов действительно существует, и количество контактов, относящихся к данной сделке равно 0, т.е. не существует связанных контактов со сделкой, то добавим автоматическую связь с контактом.

$related_accounts = $bean->get_related_list (new Account (),"accounts"); – получаем контрагента связанного, с данной сделкой. Account – это bean класс для работы с контрагентами.

if (isset ($related_accounts['list']) and count ($related_accounts['list']) == 1) – существует контрагент, связанный с этой сделкой (а иначе мы не сможем добавить связанные контакты, так как не знаем, с каким контрагентом связана сделка).

$account_bean = $related_accounts['list'][0]; — берем класс контрагента, со сделкой может быть связан только один контрагент.

$account_bean->load_relationship ('contacts'); — загружаем связь с контактами, чтобы получить связанные с этим контрагентом контакты.

$contact_list = $account_bean->contacts->getBeans (loadBean ('Contacts'));
 — получаем список связанных контактов.

if (is_array($contact_list) and count($contact_list) == 1)
{
	$contact = $contact_list[0]; //Только один контакт
	$bean->contacts->add($contact->id); //Добавим связь с этим контактом
}

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

Теперь проверяем нашу логику.

Создаем сделку. При создании сделки выбираем любого контрагента с одним связанным контактом, сохраняем сделку. И наблюдаем в субпанели сразу связь с контактом.

Субпанель контакта в модуле сделки

В следующей статьем мы обязательно рассмотрим, как на основе logic hooks SugarCRM сделать уведомления менеджерам.

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

Есть 14 коммент. к “Расширение логики модулей или Logic Hooks. Часть 2”

  1. anton:

    Ковыряюсь в Шуге, подскажите, а можно создавать папки в модуле Документы. А то как то загружать одиночные доки не совсем удобно, так как бардак очень быстро образовывается?

    • Шуга Админ:

      К сожалению, никак. Если вы хотите прикрепить папку, делайте это архивом. Или же можете разработать свой модуль — аналог модуля документы, с разбиением по папкам. Или второй, более простой вариант, делаете новый модуль — папки, без всяких полей только ID и имя. Делаете связь этого модуля с модулем документов. А в нужном вам модуле делаете связь не с модулем документов, а с модулем папки. И тогда в субпанели будут не документы, а папки, при переходе в которые вы будете видеть все документы, относящиеся к этой папке, удалять их, добавлять и т.д.

  2. anton:

    Спасибо, буду пробовать.

  3. VanVo:

    Подскажите, как можно отправить e-mail по событию. В принципе общая логика работы с хуками понятна.

    • Шуга Админ:

      Не совсем понятен Ваш вопрос. Если логика работы понятна, то в чем проблема отправки по событию? Для «отлавливания» события как раз в SugarCRM и нужны хуки. Если у Вас просто сложность отправки email сообщения, то можете воспользоваться такой функцией:

      <?php
      function sendSugarPHPMail($tos, $subject, $body){
       
      	require_once('include/SugarPHPMailer.php');
      	require_once('modules/Administration/Administration.php');
       
      	$mail = new SugarPHPMailer();
      	$admin = new Administration();
      	$admin->retrieveSettings();
       
      	if ($admin->settings['mail_sendtype'] == "SMTP") {
      		$mail->Host = $admin->settings['mail_smtpserver'];
      		$mail->Port = $admin->settings['mail_smtpport'];
       
      		if ($admin->settings['mail_smtpauth_req']) {
      			$mail->SMTPAuth = TRUE;
      			$mail->Username = $admin->settings['mail_smtpuser'];
      			$mail->Password = $admin->settings['mail_smtppass'];
      		}
       
      		$mail->Mailer   = "smtp";
      		$mail->SMTPKeepAlive = true;
       
      	}else{
      		$mail->mailer = 'sendmail';
      	}
       
      	$mail->From     = $admin->settings['notify_fromaddress'];
      	$mail->FromName = $admin->settings['notify_fromname'];
      	$mail->ContentType = "text/html"; //"text/plain"
       
      	$mail->Subject = $subject;
      	$mail->Body = $body;
       
      	foreach ($tos as $name => $address){
      		$mail->AddAddress("{$address}", "{$name}");
      	}
       
      	if (!$mail->send()) {
      		$GLOBALS['log']->info("sendSugarPHPMail - Mailer error: " . $mail->ErrorInfo);
      		return false;
      	}else{
      		return true;
      	}
      }
      ?>
      

      Где $tos — массив email, $subject — тема письма, $body — тело письма

      • VanVo:

        Большое спасибо.

        Да. Проблема была именно в отправке e-mail.

        Посмотрел Ваш код, нашел то что было неправильно в моем коде — я пытался отправлять без

        $admin = new Administration (); Ну или что-то в этом роде.

        Еще раз большое спасибо.

      • snegg:

        Здравствуйте! Я только 2 недели как разбераюсь с шугаром, если что — не пугайтесь моему вопросу...

        Вот вы написали функцию для отправки имейла по событию, например after_save.

        Правильно ли я понимаю, эту функцию нужно написать в класс, который указан в пути хука и там же следующим параметром указать эту функцию.

        А вот вопрос: там 3 параметра которые нужно передать данной функции, как это сделать?

        • Шуга Админ:

          Вам не надо заботится о передаче этих параметров, SugarCRM автоматически вызывает вашу объявленную функцию и передает ей эти три параметра: (SugarBean $bean, $event, $arguments)

  4. snegg:

    ммм

    Если вы не против, я опишу свою задачи поподробней.

    В модуле Задачи, я добавил еще 4 relate поля связаные с пользователями (ответственные над задачами).

    Соответственно рассылка при назначении идет только 1-му полю, которое было по умолчанию.

    Цель такова — мне надо отсылать письма всем назначенным над задачами.

    Если вас не затруднит, посоветуйте что-нибудь.

  5. Шуга Админ:

    Воспользуйтесь хуком, который «по вешайте» на сохранение задачи before_save, и там проверяйте если изменился пользователь ($bean->USER != $bean->fetched_row['USER']), то отправляйте письмо .

    В примере USER — заменяйте на названия своих полей, и так проверяйте все свои 4 поля.

  6. snegg:

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

               $email = new Email();
               $email->send('параметры');
               

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

  7. snegg:

    Что-то на подобие этого.

  8. Rakshas:

    Здравствуйте,

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

    Оригинал задания:

    1. Add One-to-many relationship from Accounts to Projects via install package.

    2. When Project is created and related to Account, Project name should be concatenated to Account's 'Description' field. This functionality should also be added to install package.

    у меня знания базовые, создал 2а файла:

    1й \Extension\modules\Project\Ext\logic_hooks.php

    2й \Extension\modules\Project\Ext\projectNameAddToAccauntDescription.php

    get_related_list (new Account (),"accounts");

    if (isset ($related_accounts['list']) and count ($related_accounts['list']) == 1)

    {

    $project_name = $bean->name;

    $account_bean = $related_accounts['list'][0];

    $accounts_description = $account_bean->description;

    $account_bean->description = concat ($accounts_description, ” – ”,$project_name);

    }

    else

    return;

    }

    }

    ?>

    после создания и сохранения проекта получаю ошибку 500:

    Страница suitecrm6.test.richlode.biz не работает

    Сайт suitecrm пока не может обработать этот запрос.

    HTTP ERROR 500

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

    Заранее спасибо.

Написать комментарий

Вы должны войти чтобы комментировать.