Jira的错误跟踪和客户支持? [英] Jira for bug tracking and customer support?

查看:70
本文介绍了Jira的错误跟踪和客户支持?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们正在考虑使用Jira进行错误跟踪,并将其与Git集成以将错误修复与版本处理联系起来.

We are thinking of using Jira for bug tracking and to integrate it with Git to connect bug fixes with version handling.

您是否也建议将Jira用于客户支持,或者我们是否应该为此目的找到另一个系统(例如Zendesk)?我知道可以通过某种方式将Hipchat与Jira集成在一起,以实现与客户的聊天功能,但是对于客户服务而言,Jira是否太复杂了以至于无法处理?您的经验是什么?

Do you recommend Jira also for customer support or should we find another system like for example Zendesk for that purpose? I know that it is possible somehow to integrate for example Hipchat with Jira to enable chat functionality with customers but is Jira too complex for Customer Service to handle? What is your experience?

推荐答案

我们使用Jira来获得客户支持,但是我们发现Jira缺少了为此所需的许多必备功能.这就是我们进行许多更改的原因.

We use Jira for customer support, but we found that Jira is missing many must-have features that are needed for this. that's why we make many changes.

总之,我们对选择感到非常满意,并且通过使用Jira而不是其他解决方案,我们设法节省了很多钱.

All and all, we are very happy with our choice, and we managed to save a lot of money by using Jira instead of other solutions.

这是我们进行的主要更改,这将向您显示所缺少的内容,而另一方面,您可以通过一点点编程来了解Jira可以执行任何操作:)

Here are the major changes that we made, this will show you what is missing, while on the other hand show you that with a little bit of programming, Jira can do anything :)

注意:下面编写的脚本应附加到工作流过渡中.这些脚本是使用 Jython 编写的,因此需要安装它才能使用.

Note: The scripts writen below should be attach to a workflow transition. The scripts are written using Jython, so it needs to be installed to use it.

通过电子邮件创建问题

Jira仅向Jira用户发送电子邮件.由于我们不想为每个寻求支持的人创建一个用户,因此我们改用匿名用户,并使用脚本向他们发送电子邮件.

Jira only sends emails to Jira users. Since we didn't want to create a user for every person that addressed the support, we used anonymous users instead, and used scripts to send them email.

首先,将Jira设置为通过电子邮件创建问题.然后,使用脚本运行器插入将客户的电子邮件和姓名保存到自定义字段. .代码:

First, set Jira to create issues from emails. Than, use Script Runner pluging to save customer's email and names to custom field. . code:

from com.atlassian.jira import ComponentManager
import re
cfm = ComponentManager.getInstance().getCustomFieldManager()

# read issue description
description = issue.getDescription()
if (description is not None) and ('Created via e-mail received from' in description):
    # extract email and name:
    if ('<' in description) and ('>' in description):
        # pattern [Created via e-mail received from: name <email@company.com>]
        # split it to a list
        description_list = re.split('<|>|:',description)
        list_length = len(description_list)
        for index in range(list_length-1, -1, -1):
            if '@' in description_list[index]:
                customer_email = description_list[index]
                customer_name = description_list[index - 1]
                break
    else:
        # pattern [Created via e-mail received from: email@company.com]
        customer_name = "Sir or Madam"
        # split it to a list  
        description_list = re.split(': |]',description)
        list_length = len(description_list)
        for index in range(list_length-1, -1, -1):
            if '@' in description_list[index]:
                customer_email = description_list[index]
                break

    # if the name isn't in the right form, switch it's places:
    if (customer_name[0] == '"') and (customer_name[-1] == '"') and (',' in customer_name):
        customer_name = customer_name[1:-1]
        i =  customer_name.index(',')
        customer_name = customer_name[i+2:]+" "+customer_name[:i]

    # insert data to issue fields
    issue.setCustomFieldValue(cfm.getCustomFieldObject("customfield_10401"),customer_email)
    issue.setCustomFieldValue(cfm.getCustomFieldObject("customfield_10108"),customer_name)

发送客户issue created通知

Send customer issue created notification

使用以下脚本发送邮件:

Send the mail using the following script:

import smtplib,email
from smtplib import SMTP 
from email.MIMEMultipart import MIMEMultipart
from email.MIMEBase import MIMEBase
from email.MIMEText import MIMEText
from email import Encoders
import os
import re
from com.atlassian.jira import ComponentManager

customFieldManager = ComponentManager.getInstance().getCustomFieldManager()
cfm = ComponentManager.getInstance().getCustomFieldManager()

# read needed fields from the issue
key = issue.getKey()
#status = issue.getStatusObject().name
summary = issue.getSummary()
project = issue.getProjectObject().name

# read customer email address
toAddr = issue.getCustomFieldValue(cfm.getCustomFieldObject("customfield_10401"))
# send mail only if a valid email was entered
if (toAddr is not None) and (re.match('[A-Za-z0-9._%+-]+@(?:[A-Za-z0-9-]+\.)+[A-Za-z]{2,4}',toAddr)):
    # read customer name
    customerName = issue.getCustomFieldValue(cfm.getCustomFieldObject("customfield_10108"))
    # read template from the disk
    template_file = 'new_case.template'
    f = open(template_file, 'r')
    htmlBody = ""
    for line in f:
        line = line.replace('$$CUSTOMER_NAME',customerName)
        line = line.replace('$$KEY',key)
        line = line.replace('$$PROJECT',project)
        line = line.replace('$$SUMMARY',summary)
        htmlBody += line + '<BR>'


    smtpserver = 'smtpserver.com'
    to = [toAddr]
    fromAddr = 'jira@email.com'
    subject = "["+key+"] Thank You for Contacting Support team"
    mail_user = 'jira@email.com'
    mail_password = 'password'

    # create html email
    html = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" '
    html +='"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml">'
    html +='<body style="font-size:12px;font-family:Verdana">'
    html +='<p align="center"><img src="http://path/to/company_logo.jpg" alt="logo"></p> '
    html +='<p>'+htmlBody+'</p>'
    html +='</body></html>'

    emailMsg = email.MIMEMultipart.MIMEMultipart('alternative')
    emailMsg['Subject'] = subject
    emailMsg['From'] = fromAddr
    emailMsg['To'] = ', '.join(to)
    emailMsg.attach(email.mime.text.MIMEText(html,'html'))

    # Send the email
    s = SMTP(smtpserver) # ip or domain name of smtp server
    s.login(mail_user, mail_password)   
    s.sendmail(fromAddr, [to], emailMsg.as_string())
    s.quit()

    # add sent mail to comments
    cm = ComponentManager.getInstance().getCommentManager()
    email_body = htmlBody.replace('<BR>','\n')
    cm.create(issue,'anonymous','Email was sent to the customer ; Subject: '+subject+'\n'+email_body,False)

new_case.template的内容:

Dear $$CUSTOMER_NAME,

Thank you for contacting support team.

We will address your case as soon as possible and respond with a solution very quickly.

Issue key $$KEY has been created as a reference for future correspondence.

If you need urgent support please refer to our Frequently Asked Questions page at http://www.example.com/faq.

Thank you,

Support Team


Issue key: $$KEY
Issue subject: $$PROJECT
Issue summary: $$SUMMARY

问题提醒-打开24/36/48小时通知

  • 创建了一个名为自此之后开始"的自定义字段-一个日期时间"字段,用于保存问题的打开时间.
  • 创建了一个名为通知"的自定义字段-只读文本字段.
  • 使用脚本运行器插入,我已经创建了后功能,并将其置于每次转换为打开"状态的时间.这是为了保持问题的开放时间.
  • Created a custom field called "Open since" - a 'Date Time' field to hold the time the issue has been opened.
  • Created a custom field called "Notification" - a read only text field.
  • Using the Script Runner pluging , I've created a post-function and placed it on every transition going to the 'Open' status. This is to keep the issue opening time.

代码:

from com.atlassian.jira import ComponentManager
from datetime import datetime

opend_since_field = "customfield_10001"

# get opened since custom field:
cfm = ComponentManager.getInstance().getCustomFieldManager()
# get current time
currentTime = datetime.today()
# save current time
issue.setCustomFieldValue(cfm.getCustomFieldObject(opend_since_field),currentTime)

  • 我创建了一个新的过滤器,以获取开放时间超过24小时的问题列表:
  • JQL:

    project = XXX AND status= Open ORDER BY updated ASC, key DESC
    

    • 最后-我使用了 Jira远程API - XML-RPC 方法来编写计划用于每5分钟运行一次.剧本 从过滤器读取所有发出的消息,将所有处于打开"状态的消息拉出24小时/36小时/48小时以上,发送提醒电子邮件,并将其标记为已通知,因此将仅发送每种类型的提醒.
      • Lastly - I've used the Jira remote API - the XML-RPC method to write a python script scheduled to run every 5 minutes. The script reads all the issued from the filter, pulls all of them that have an 'Open' status for over 24h/36h/48h, send a reminder email, and mark them as notified, so only one reminder of each type will be sent.
      • python代码:

        #!/usr/bin/python
        
        # Refer to the XML-RPC Javadoc to see what calls are available:
        # http://docs.atlassian.com/software/jira/docs/api/rpc-jira-plugin/latest/com/atlassian/jira/rpc/xmlrpc/XmlRpcService.html
        # /home/issues_reminder.py
        
        import xmlrpclib
        import time
        from time import mktime
        from datetime import datetime
        from datetime import timedelta
        import smtplib,email
        from smtplib import SMTP 
        from email.MIMEMultipart import MIMEMultipart
        from email.MIMEBase import MIMEBase
        from email.MIMEText import MIMEText
        from email import Encoders
        
        # Jira connction info
        server = 'https://your.jira.com/rpc/xmlrpc'
        user = 'user'
        password = 'password'
        filter = '10302' # Filter ID
        # Email definitions 
        smtpserver = 'mail.server.com'
        fromAddr = 'support@your.jira.com'
        mail_user = 'jira_admin@your.domain.com'
        mail_password = 'password'
        toAddr = 'support@your.domain.com'
        mysubject = "hrs Issue notification!!!"
        opend_since_field = "customfield_10101"
        
        
        COMMASPACE = ', '
        def email_issue(issue,esc_time):
            # create html email
            subject = '['+issue+'] '+esc_time+mysubject
            html = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" '
            html +='"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml">'
            html +='<body style="font-size:12px;font-family:Verdana">'
            html +='<p align="center"><img src="your_logo.jpg" alt="logo" height="43" width="198"></p> '
            html +='<p> The issue ['+issue+'] is open for over '+esc_time+' hours.</p>'
            html +='<p> A link to view the issue: https://your.jira.com/browse/'+issue+'.</p>'
            html +='<BR><p> This is an automated email sent from Jira.</p>'
            html +='</body></html>'
            emailMsg = email.MIMEMultipart.MIMEMultipart('alternative')
            emailMsg['Subject'] = subject
            emailMsg['From'] = fromAddr
            emailMsg['To'] = toAddr
            emailMsg.attach(MIMEText(html, 'html'))
            # Send the email
            emailserver = SMTP(smtpserver) # ip or domain name of smtp server
            emailserver.login(mail_user, mail_password)
            emailserver.sendmail(fromAddr, [toAddr], emailMsg.as_string())
            emailserver.quit()
            return
        
        
        s = xmlrpclib.ServerProxy(server)
        auth = s.jira1.login(user, password)
        
        esc12List = []
        esc24List = []
        esc48List = []
        
        
        issues = s.jira1.getIssuesFromFilter(auth, filter)
        print "Modifying issue..."
        for issue in issues:
                creation = 0;
                # get open since time
                for customFields in issue['customFieldValues']:
                        if customFields['customfieldId'] == opend_since_field :
                                print "found field!"+  customFields['values']
                                creation = customFields['values']
                if (creation == 0):
                        creation = issue['created']
                        print "field not found"
            creationTime = datetime.fromtimestamp(mktime(time.strptime(creation, '%d/%b/%y %I:%M %p')))
            currentTime = datetime.fromtimestamp(mktime(time.gmtime()))
            delta = currentTime - creationTime
            esc12 = timedelta(hours=12)
            esc24 = timedelta(hours=24)
            esc48 = timedelta(hours=48)
            print "\nchecking issue "+issue['key']
            if (delta < esc12):
                print "less than 12 hours"
                print "not updating"
                continue
            if (delta < esc24):
                print "less than 24 hours"
                for customFields in issue['customFieldValues']:
                    if customFields['customfieldId'] == 'customfield_10412':
                        if customFields['values'] == '12h':
                            print "not updating"
                            break
                        else:
                            print "updating !!!"
                            s.jira1.updateIssue(auth, issue['key'], {"customfield_10412": ["12h"]})
                            esc12List.append(issue['key'])
                            break
                continue
            if (delta < esc48):
                print "less than 48 hours"
                for customFields in issue['customFieldValues']:
                    if customFields['customfieldId'] == 'customfield_10412':
                        if customFields['values'] == '24h':
                            print "not updating"
                            break
                        else:
                            print "updating !!!"
                            s.jira1.updateIssue(auth, issue['key'], {"customfield_10412": ["24h"]})
                            esc24List.append(issue['key'])
                            break
                continue
            print "more than 48 hours"
            for customFields in issue['customFieldValues']:
                if customFields['customfieldId'] == 'customfield_10412':
                    if customFields['values'] == '48h':
                        print "not updating"
                        break
                    else:
                        print "updating !!!"
                        s.jira1.updateIssue(auth, issue['key'], {"customfield_10412": ["48h"]})
                        esc48List.append(issue['key'])
                        break
        
        for key in esc12List:
            email_issue(key,'12')
        for key in esc24List:
            email_issue(key,'24')
        for key in esc48List:
            email_issue(key,'48')
        

        此方法的主要优点是高度可自定义,并且通过将数据保存到自定义字段,可以轻松创建过滤器和报告以显示已存在很长时间的问题.

        The main pros of this method is that it's highly customizable, and by saving the data to custom fields it's easy to create filters and reports to show issues that have been opened for a long time.

        上报给开发团队

        创建一个新的过渡-Escalate.这将为开发团队创建一个问题,并将新问题链接到支持问题.添加以下发布功能:

        Create a new transition - Escalate. This will create an issue for the development team, and link the new issue to the support issue. Add the following post function:

        from com.atlassian.jira.util import ImportUtils
        from com.atlassian.jira import ManagerFactory
        from com.atlassian.jira.issue import MutableIssue
        from com.atlassian.jira import ComponentManager
        from com.atlassian.jira.issue.link import DefaultIssueLinkManager
        from org.ofbiz.core.entity import GenericValue;
        
        # get issue objects
        issueManager = ComponentManager.getInstance().getIssueManager()
        issueFactory = ComponentManager.getInstance().getIssueFactory()
        authenticationContext = ComponentManager.getInstance().getJiraAuthenticationContext()
        issueLinkManager = ComponentManager.getInstance().getIssueLinkManager()
        customFieldManager = ComponentManager.getInstance().getCustomFieldManager()
        userUtil = ComponentManager.getInstance().getUserUtil()
        projectMgr = ComponentManager.getInstance().getProjectManager()
        customer_name = customFieldManager.getCustomFieldObjectByName("Customer Name")
        customer_email = customFieldManager.getCustomFieldObjectByName("Customer Email")
        escalate = customFieldManager.getCustomFieldObjectByName("Escalate to Development")
        
        if issue.getCustomFieldValue(escalate) is not None:
            # define issue
            issueObject = issueFactory.getIssue()
            issueObject.setProject(projectMgr.getProject(10000))
            issueObject.setIssueTypeId("1") # bug
            # set subtask attributes
            issueObject.setSummary("[Escalated from support] "+issue.getSummary())
            issueObject.setAssignee(userUtil.getUserObject("nadav"))
            issueObject.setReporter(issue.getAssignee())
            issueObject.setDescription(issue.getDescription())
            issueObject.setCustomFieldValue(customer_name, issue.getCustomFieldValue(customer_name)+" "+issue.getCustomFieldValue(customer_email))
            issueObject.setComponents(issue.getComponents())
            # Create subtask 
            subTask = issueManager.createIssue(authenticationContext.getUser(), issueObject)
            # Link parent issue to subtask
            issueLinkManager.createIssueLink(issueObject.getId(),issue.getId(),10003,1,authenticationContext.getUser())
            # Update search indexes
            ImportUtils.setIndexIssues(True);
            ComponentManager.getInstance().getIndexManager().reIndex(subTask)
            ImportUtils.setIndexIssues(False)
        

        转向销售

        创建一个新的过渡-Move to sales.许多支持电话最终都变成了销售电话,这会将问题移交给销售团队.添加以下发布功能:

        reate a new transition - Move to sales. Many support calls end up as a sale call, this will move the issue to the sales team. Add the following post function:

        from com.atlassian.jira.util import ImportUtils
        from com.atlassian.jira.issue import MutableIssue
        from com.atlassian.jira import ComponentManager
        
        customFieldManager = ComponentManager.getInstance().getCustomFieldManager()
        userUtil = ComponentManager.getInstance().getUserUtil()
        
        issue.setStatusId("1");
        issue.setAssignee(userUtil.getUserObject("John"))
        issue.setSummary("[Moved from support] "+issue.getSummary())
        issue.setProjectId(10201);
        issue.setIssueTypeId("35");
        ImportUtils.setIndexIssues(True);
        ComponentManager.getInstance().getIndexManager().reIndex(issue)
        ImportUtils.setIndexIssues(False)
        
        
        # add to comments
        from time import gmtime, strftime
        time = strftime("%d-%m-%Y %H:%M:%S", gmtime())
        cm = ComponentManager.getInstance().getCommentManager()
        currentUser = ComponentManager.getInstance().getJiraAuthenticationContext().getUser().toString()
        cm.create(issue,currentUser,'Email was moved to Sales at '+time,False)
        

        这篇关于Jira的错误跟踪和客户支持?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆