更新VTiger中的现有故障单

时间:2010-10-21 08:27:10

标签: php crm issue-tracking ticket-system vtiger

我是VTiger的新手,我正在使用5.2.0版试用,学习实施问题跟踪。

说明:

客户端发送电子邮件至support@company.com,Mail Converter或Mail Scanner ..扫描新电子邮件,如果找到则创建新票证。

如果管理员看到在故障单中引发的新故障单,进行一些更改,例如将其分配给某人或发表评论等.VTiger CRM会向客户发送一封电子邮件,说明管理员已对其进行了修改票。

让我们说客户想要进行一些更改,所以他回复了support@company.com,因为收到新邮件而邮件扫描程序创建了一张新票,所以会引发新票。

问题:

不是更新客户端之前发送的现有票证,而是每次创建新票证,通过为一个问题制作许多票证来重复问题,这是一个大问题。

当客户向mailcompany.com发送邮件时,电子邮件的主题将作为故障单的标题和电子邮件正文作为故障单的描述。

让我们说

Title of Ticket is SubjectClientSent

客户端在管理员进行一些修改后并不喜欢某些内容,客户端决定回复VTiger发送给他的电子邮件,通常都是这样。

Re: TT17 [ Ticket Id : 22 ] Re : SubjectClientSent

我不希望Mail Scanner创建一个标题为Re: TT17 [ Ticket Id : 22 ] Re : SubjectClientSent的新票证,我希望它更新标题为SubjectClientSent

的票证

我尝试创建一个像这样的新规则。

alt text

但是,它仍在创造一张新票。

你能帮我纠正一下吗?

有更好的方法来更新现有的门票吗?

感谢您的帮助和支持。

1 个答案:

答案 0 :(得分:2)

找到了解决方案!

整个答案是从VTiger PDF documentVTiger ForumVTiger Bug Link

中窃取信息的

以下图片显示了使用MailScanner或MailConverter自动化票证所涉及的基本流程

![邮件扫描程序基本流程] [4]

<强> 1 客户(具有联系人/帐户记录)向主题发送电子邮件至support@company.com “测试故障单”

<强> 2 Mail Scanner创建票证,将其链接到通过emailid过滤的匹配联系人/帐户记录 抬头。 HelpDeskHandler将发送一封确认电子邮件,其中包含有关如何回复的更多信息 进一步对客户。电子邮件主题看起来像“TT15 [Ticket Id:1483] Test Trouble Ticket”

第3: 客户回复确认电子邮件,保留主题的一部分 support@company.com。由于邮件扫描程序在主题上配置了Regex规则并找到了 匹配链接到客户的故障单,它会使用电子邮件正文更新评论。

<强> 4 当支持团队更新他们的评论时,会再次向客户发送电子邮件。

以下步骤将帮助我们实现此功能

步骤1:设置发送邮件服务器

如果您的外发邮件服务器是Gmail,则以下设置应该适用于您

Mail Server Settings (SMTP)     
Server Name ssl://smtp.gmail.com:465 
User Name   username@gmail.com 
Password    ******  
From Email  from.email@gmail.com 
Requires Authentication?    Yes 

第2步:设置MailScanner或MailConverter

DEFAULT Information 

Scanner Name    DEFAULT
Server Name     imap.gmail.com
Protocol       imap4
User Name     support.company@gmail.com
SSL Type       ssl
SSL Method      novalidate-cert
Connect URL     {imap.gmail.com:993/imap4/ssl/novalidate-cert}
Status       Enabled

Scanning Information 

Look for    All Messages from lastscan
After scan   Mark message as Read

步骤3:设置规则以创建&amp;在MailScanner或MailConverter中更新票证

Rules For Mail Converter [DEFAULT] 

    Priority    
    From    
    To  
    Subject     Regex   Ticket Id[^:]?: ([0-9]+)
    Body        
    Match   All Condition
    Action  Update Ticket

    Priority    
    From    
    To  
    Subject         
    Body        
    Match   Any Condition
    Action  Create Ticket 

第4步:配置config.inc.php

更新config.inc.php中的以下变量

<强> $ HELPDESK_SUPPORT_EMAIL_ID

FROM发送邮件时使用的地址信息 示例:automated-reply@company.com

$HELPDESK_SUPPORT_EMAIL_ID = 'auto.reply.company@gmail.com';

<强> $ HELPDESK_SUPPORT_NAME

FROM名称,用于显示已发送的电子邮件。 示例:自动回复

$HELPDESK_SUPPORT_NAME = 'Company Support';

<强> $ HELPDESK_SUPPORT_EMAIL_REPLY_ID

在发送的电子邮件中设置的REPLY-TO地址。 示例:support@company.com

$HELPDESK_SUPPORT_EMAIL_REPLY_ID = 'support.company@gmail.com';

设置此信息是自动选票的重要步骤之一。 当用户尝试回复自动电子邮件TO时 地址将由邮件客户端设置并到达MailBox for 我们设置了扫描。

步骤5:在VTigerCRM / modules / HelpDesk / 中创建HelpDeskHandler.php

<?php
/*+**********************************************************************************
 * The contents of this file are subject to the vtiger CRM Public License Version 1.0
 * ("License"); You may not use this file except in compliance with the License
 * The Original Code is:  vtiger CRM Open Source
 * The Initial Developer of the Original Code is vtiger.
 * Portions created by vtiger are Copyright (C) vtiger.
 * All Rights Reserved.
 ************************************************************************************/

class HelpDeskHandler extends VTEventHandler {

  function __getSendToEmail($crmid) {
    if(empty($crmid)) return false;

    $sendtoemail = false;

    global $adb;

    $metaresult = $adb->pquery("SELECT setype FROM vtiger_crmentity WHERE crmid=? AND deleted = 0", array($crmid));
    if($metaresult && $adb->num_rows($metaresult)) {
      $metaresultrow = $adb->fetch_array($metaresult);

      $emailres = false;

      if($metaresultrow['setype'] == 'Contacts') {
        $emailres = $adb->pquery("SELECT email,yahooid FROM vtiger_contactdetails WHERE contactid = ?", array($crmid));
      } else if($metaresultrow['setype'] == 'Accounts') {
        $emailres = $adb->pquery("SELECT email1,email2 FROM vtiger_account WHERE accountid = ?", array($crmid));
      }

      if($emailres && $adb->num_rows($emailres)) {
        $emailresrow = $adb->fetch_array($emailres);

        if(!empty($emailresrow[0])) $sendtoemail = $emailresrow[0];
        if(!empty($emailresrow[1])) $sendtoemail = $emailresrow[1];

      }

    }
    return $sendtoemail;

  }


  function handleEvent($eventName, $entityData) {
    global $log, $adb;

    if($eventName == 'vtiger.entity.aftersave') {
      $moduleName = $entityData->getModuleName();

      // Event not related to HelpDesk - IGNORE
      if($moduleName != 'HelpDesk') {
        return;
      }

      // Take action if the service running is MailScanner (either via Cron/Scan Now)
      if(isset($_REQUEST) && $_REQUEST['service'] == 'MailScanner' ) {

        $focus = $entityData->focus;

        $sendToEmail = $this->__getSendToEmail($focus->column_fields['parent_id']); 

        // If the entity is create new and we know whom to send the mail proceed.
        if($entityData->isNew() && $sendToEmail) {
          global $HELPDESK_SUPPORT_EMAIL_ID, $HELPDESK_SUPPORT_NAME, $HELPDESK_SUPPORT_EMAIL_REPLY_ID;

          include_once 'vtlib/Vtiger/Mailer.php';
          $mailer = new Vtiger_Mailer();
          $mailer->ConfigSenderInfo($HELPDESK_SUPPORT_EMAIL_ID, $HELPDESK_SUPPORT_NAME);
          $mailer->AddReplyTo($HELPDESK_SUPPORT_EMAIL_REPLY_ID);

          $mailer->initFromTemplate('Auto Ticket First Response Template');

          // Update the email subject
          $mailer->Subject = sprintf("%s [ Ticket Id : %s ] Re : %s",
            $focus->column_fields['ticket_no'],
            $focus->id,
            $focus->column_fields['ticket_title']
          );

          $mailer->SendTo( $sendToEmail, '', false, false, true );
        }
      }        
    }
  }
}

?>

步骤6:创建名为“Auto Ticket First Response”的电子邮件模板

这是客户向support.company@gmail.com发送电子邮件后公司支持自动发送的确认电子邮件

要创建电子邮件模板,请转到“设置/电子邮件模板”;选择新模板并将其命名为“Auto Ticket First Response”

步骤7:创建一个新的PHP文件并将其命名为RegisterHelpDeskHandler.php

放置以下代码&amp;执行文件

<?php
/*+**********************************************************************************
 * The contents of this file are subject to the vtiger CRM Public License Version 1.0
 * ("License"); You may not use this file except in compliance with the License
 * The Original Code is:  vtiger CRM Open Source
 * The Initial Developer of the Original Code is vtiger.
 * Portions created by vtiger are Copyright (C) vtiger.
 * All Rights Reserved.
 ************************************************************************************/

$Vtiger_Utils_Log = true;

include_once 'vtlib/Vtiger/Module.php';
include_once 'vtlib/Vtiger/Event.php';

$moduleInstance = Vtiger_Module::getInstance('HelpDesk');
Vtiger_Event::register($moduleInstance, 'vtiger.entity.aftersave', 'HelpDeskHandler', 'modules/HelpDesk/HelpDeskHandler.php');
?>

要执行,只需输入以下网址

即可
http://localhost:8888/registerHelpDeskHandler.php

您应该在浏览器中看到以下输出

Registering Event vtiger.entity.aftersave with [modules/HelpDesk/HelpDeskHandler.php] HelpDeskHandler ... DONE

第9步:检查错误!

如果您使用的是VTiger 5.2.0,该错误已经修复!

如果不是,请转到modules / Settings / MailScanner / core / MailScannerAction.php并使用以下代码替换整个代码

<?php
/*********************************************************************************
 ** The contents of this file are subject to the vtiger CRM Public License Version 1.0
 * ("License"); You may not use this file except in compliance with the License
 * The Original Code is:  vtiger CRM Open Source
 * The Initial Developer of the Original Code is vtiger.
 * Portions created by vtiger are Copyright (C) vtiger.
 * All Rights Reserved.
 *
 ********************************************************************************/

require_once('modules/Emails/Emails.php');
require_once('modules/HelpDesk/HelpDesk.php');
require_once('modules/Users/Users.php');
require_once('modules/Documents/Documents.php');

/**
 * Mail Scanner Action
 */
class Vtiger_MailScannerAction {
    // actionid for this instance
    var $actionid  = false; 
    // scanner to which this action is associated
    var $scannerid = false;
    // type of mailscanner action
    var $actiontype= false;
    // text representation of action
    var $actiontext= false;
    // target module for action
    var $module    = false;
    // lookup information while taking action
    var $lookup    = false;

    // Storage folder to use
    var $STORAGE_FOLDER = 'storage/mailscanner/';

    /** DEBUG functionality */
    var $debug     = false;
    function log($message) {
        global $log;
        if($log && $this->debug) { $log->debug($message); }
        else if($this->debug) echo "$message\n";
    }

    /**
     * Constructor.
     */
    function __construct($foractionid) {
        $this->initialize($foractionid);        
    }

    /**
     * Initialize this instance.
     */
    function initialize($foractionid) {
        global $adb;
        $result = $adb->pquery("SELECT * FROM vtiger_mailscanner_actions WHERE actionid=? ORDER BY sequence", Array($foractionid));

        if($adb->num_rows($result)) {
            $this->actionid   = $adb->query_result($result, 0, 'actionid');
            $this->scannerid  = $adb->query_result($result, 0, 'scannerid');
            $this->actiontype = $adb->query_result($result, 0, 'actiontype');
            $this->module     = $adb->query_result($result, 0, 'module');
            $this->lookup     = $adb->query_result($result, 0, 'lookup');
            $this->actiontext = "$this->actiontype,$this->module,$this->lookup";
        }
    }

    /**
     * Create/Update the information of Action into database.
     */
    function update($ruleid, $actiontext) {
        global $adb;

        $inputparts = explode(',', $actiontext);
        $this->actiontype = $inputparts[0]; // LINK, CREATE
        $this->module     = $inputparts[1]; // Module name
        $this->lookup     = $inputparts[2]; // FROM, TO

        $this->actiontext = $actiontext;

        if($this->actionid) {
            $adb->pquery("UPDATE vtiger_mailscanner_actions SET scannerid=?, actiontype=?, module=?, lookup=? WHERE actionid=?",
                Array($this->scannerid, $this->actiontype, $this->module, $this->lookup, $this->actionid));
        } else {
            $this->sequence = $this->__nextsequence();
            $adb->pquery("INSERT INTO vtiger_mailscanner_actions(scannerid, actiontype, module, lookup, sequence) VALUES(?,?,?,?,?)",
                Array($this->scannerid, $this->actiontype, $this->module, $this->lookup, $this->sequence));
            $this->actionid = $adb->database->Insert_ID();
        }
        $checkmapping = $adb->pquery("SELECT COUNT(*) AS ruleaction_count FROM vtiger_mailscanner_ruleactions 
            WHERE ruleid=? AND actionid=?", Array($ruleid, $this->actionid));
        if($adb->num_rows($checkmapping) && !$adb->query_result($checkmapping, 0, 'ruleaction_count')) {
            $adb->pquery("INSERT INTO vtiger_mailscanner_ruleactions(ruleid, actionid) VALUES(?,?)", 
                Array($ruleid, $this->actionid));
        }
    }

    /**
     * Delete the actions from tables.
     */
    function delete() {
        global $adb;
        if($this->actionid) {
            $adb->pquery("DELETE FROM vtiger_mailscanner_actions WHERE actionid=?", Array($this->actionid));
            $adb->pquery("DELETE FROM vtiger_mailscanner_ruleactions WHERE actionid=?", Array($this->actionid));
        }
    }

    /**
     * Get next sequence of Action to use.
     */
    function __nextsequence() {
        global $adb;
        $seqres = $adb->pquery("SELECT max(sequence) AS max_sequence FROM vtiger_mailscanner_actions", Array());
        $maxsequence = 0;
        if($adb->num_rows($seqres)) {
            $maxsequence = $adb->query_result($seqres, 0, 'max_sequence');
        }
        ++$maxsequence;
        return $maxsequence;
    }

    /**
     * Apply the action on the mail record.
     */
    function apply($mailscanner, $mailrecord, $mailscannerrule, $matchresult) {
        $returnid = false;
        if($this->actiontype == 'CREATE') {
            if($this->module == 'HelpDesk') {
                $returnid = $this->__CreateTicket($mailscanner, $mailrecord); 
            }
        } else if($this->actiontype == 'LINK') {
            $returnid = $this->__LinkToRecord($mailscanner, $mailrecord);
        } else if($this->actiontype == 'UPDATE') {
            if($this->module == 'HelpDesk') {
                $returnid = $this->__UpdateTicket($mailscanner, $mailrecord, 
                    $mailscannerrule->hasRegexMatch($matchresult));
            }
        }
        return $returnid;
    }

    /**
     * Update ticket action.
     */
    function __UpdateTicket($mailscanner, $mailrecord, $regexMatchInfo) {
        global $adb;
        $returnid = false;

        $usesubject = false;
        if($this->lookup == 'SUBJECT') {
            // If regex match was performed on subject use the matched group
            // to lookup the ticket record
            if($regexMatchInfo) $usesubject = $regexMatchInfo['matches'];
            else $usesubject = $mailrecord->_subject;

            // Get the ticket record that was created by SENDER earlier
            $fromemail = $mailrecord->_from[0];

            $linkfocus = $mailscanner->GetTicketRecord($usesubject, $fromemail);
            $relatedid = $linkfocus->column_fields[parent_id];

            // If matching ticket is found, update comment, attach email
            if($linkfocus) {
                $timestamp = $adb->formatDate(date('YmdHis'), true);
                $adb->pquery("INSERT INTO vtiger_ticketcomments(ticketid, comments, ownerid, ownertype, createdtime) VALUES(?,?,?,?,?)",
                    Array($linkfocus->id, $mailrecord->getBodyText(), $relatedid, 'customer', $timestamp));
                // Set the ticket status to Open if its Closed
                $adb->pquery("UPDATE vtiger_troubletickets set status=? WHERE ticketid=? AND status='Closed'", Array('Open', $linkfocus->id));

                $returnid = $this->__CreateNewEmail($mailrecord, $this->module, $linkfocus);

            } else {
                // TODO If matching ticket was not found, create ticket?
                // $returnid = $this->__CreateTicket($mailscanner, $mailrecord);
            }
        }
        return $returnid;
    }

    /**
     * Create ticket action.
     */
    function __CreateTicket($mailscanner, $mailrecord) {
        // Prepare data to create trouble ticket
        $usetitle = $mailrecord->_subject;
        $description = $mailrecord->getBodyText();

        // There will be only on FROM address to email, so pick the first one
        $fromemail = $mailrecord->_from[0]; 
        $linktoid = $mailscanner->LookupContact($fromemail);
        if(!$linktoid) $linktoid = $mailscanner->LookupAccount($fromemail);

        /** Now Create Ticket **/
        global $current_user;
        if(!$current_user) $current_user = new Users();
        $current_user->id = 1;

        // Create trouble ticket record
        $ticket = new HelpDesk();
        $ticket->column_fields['ticket_title'] = $usetitle;
        $ticket->column_fields['description'] = $description;
        $ticket->column_fields['ticketstatus'] = 'Open';
        $ticket->column_fields['assigned_user_id'] = $current_user->id;
        if($linktoid) $ticket->column_fields['parent_id'] = $linktoid;
        $ticket->save('HelpDesk');

        // Associate any attachement of the email to ticket
        $this->__SaveAttachements($mailrecord, 'HelpDesk', $ticket);

        return $ticket->id;
    }

    /**
     * Add email to CRM record like Contacts/Accounts
     */
    function __LinkToRecord($mailscanner, $mailrecord) {
        $linkfocus = false;

        $useemail  = false;
        if($this->lookup == 'FROM') $useemail = $mailrecord->_from;
        else if($this->lookup == 'TO') $useemail = $mailrecord->_to;

        if($this->module == 'Contacts') {
            foreach($useemail as $email) {
                $linkfocus = $mailscanner->GetContactRecord($email);
                if($linkfocus) break;
            }
        } else if($this->module == 'Accounts') {
            foreach($useemail as $email) {          
                $linkfocus = $mailscanner->GetAccountRecord($email);
                if($linkfocus) break;
            }
        }

        $returnid = false;
        if($linkfocus) {
            $returnid = $this->__CreateNewEmail($mailrecord, $this->module, $linkfocus);
        }
        return $returnid;
    }

    /**
     * Create new Email record (and link to given record) including attachements
     */
    function __CreateNewEmail($mailrecord, $module, $linkfocus) {   
        global $current_user, $adb;
        if(!$current_user) $current_user = new Users();
        $current_user->id = 1;

        $focus = new Emails();
        $focus->column_fields['parent_type'] = $module;
        $focus->column_fields['activitytype'] = 'Emails';
        $focus->column_fields['parent_id'] = "$linkfocus->id@-1|";
        $focus->column_fields['subject'] = $mailrecord->_subject;

        $focus->column_fields['description'] = $mailrecord->getBodyHTML();
        $focus->column_fields['assigned_user_id'] = $linkfocus->column_fields['assigned_user_id'];
        $focus->column_fields["date_start"]= date('Y-m-d', $mailrecord->_date);

        $from=$mailrecord->_from[0];
        $to = $mailrecord->_to[0];
        $cc = (!empty($mailrecord->_cc))? implode(',', $mailrecord->_cc) : '';
        $bcc= (!empty($mailrecord->_bcc))? implode(',', $mailrecord->_bcc) : '';
        $flag=''; // 'SENT'/'SAVED'
        //emails field were restructured and to,bcc and cc field are JSON arrays
        $focus->column_fields['from_email'] = $from;
        $focus->column_fields['saved_toid'] = $to;
        $focus->column_fields['ccmail'] = $cc;
        $focus->column_fields['bccmail'] = $bcc;  
        $focus->save('Emails');

        $emailid = $focus->id;

        $this->log("Created [$focus->id]: $mailrecord->_subject linked it to " . $linkfocus->id);

        // TODO: Handle attachments of the mail (inline/file)
        $this->__SaveAttachements($mailrecord, 'Emails', $focus);

        return $emailid;
    }

    /**
     * Save attachments from the email and add it to the module record.
     */
    function __SaveAttachements($mailrecord, $basemodule, $basefocus) {
        global $adb;

        // If there is no attachments return
        if(!$mailrecord->_attachments) return;

        $userid = $basefocus->column_fields['assigned_user_id'];
        $setype = "$basemodule Attachment";

        $date_var = $adb->formatDate(date('YmdHis'), true);

        foreach($mailrecord->_attachments as $filename=>$filecontent) {
            $attachid = $adb->getUniqueId('vtiger_crmentity');
            $description = $filename;
            $usetime = $adb->formatDate($date_var, true);

            $adb->pquery("INSERT INTO vtiger_crmentity(crmid, smcreatorid, smownerid, 
                modifiedby, setype, description, createdtime, modifiedtime, presence, deleted)
                VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", 
                Array($attachid, $userid, $userid, $userid, $setype, $description, $usetime, $usetime, 1, 0));

            $issaved = $this->__SaveAttachmentFile($attachid, $filename, $filecontent);
            if($issaved) {
                // Create document record
                $document = new Documents();
                $document->column_fields['notes_title']      = $filename;
                $document->column_fields['filename']         = $filename;
                $document->column_fields['filestatus']       = 1;
                $document->column_fields['filelocationtype'] = 'I';
                $document->column_fields['folderid']         = 1; // Default Folder 
                $document->column_fields['assigned_user_id'] = $userid;
                $document->save('Documents');

                // Link file attached to document
                $adb->pquery("INSERT INTO vtiger_seattachmentsrel(crmid, attachmentsid) VALUES(?,?)", 
                    Array($document->id, $attachid));

                // Link document to base record
                $adb->pquery("INSERT INTO vtiger_senotesrel(crmid, notesid) VALUES(?,?)", 
                    Array($basefocus->id, $document->id));              
            }
        }   
    }

    /**
     * Save the attachment to the file
     */
    function __SaveAttachmentFile($attachid, $filename, $filecontent) {
        global $adb;

        $dirname = $this->STORAGE_FOLDER;
        if(!is_dir($dirname)) mkdir($dirname);

        $description = $filename;
        $filename = str_replace(' ', '-', $filename);
        $saveasfile = "$dirname$attachid" . "_$filename";
        if(!file_exists($saveasfile)) {

            $this->log("Saved attachement as $saveasfile\n");

            $fh = fopen($saveasfile, 'wb');
            fwrite($fh, $filecontent);
            fclose($fh);
        }

        $mimetype = MailAttachmentMIME::detect($saveasfile);

        $adb->pquery("INSERT INTO vtiger_attachments SET attachmentsid=?, name=?, description=?, type=?, path=?",
            Array($attachid, $filename, $description, $mimetype, $dirname));

        return true;
    }
}
?>

步骤10:如果您仍然遇到问题,仍然无法获得更新票证功能;  查看VTiger论坛。

[4]:http://i.stack.imgur.com/5ZU7Q.jpg 强调文字 *强调文字*