吉拉的bug跟踪和客户支持?(Jira for bug tracking and customer

2019-08-17 08:56发布

我们正在考虑使用JIRA来bug跟踪,并把它与Git的整合,bug修复版本与处理连接。

你建议吉拉也为客户支持或我们应该找到另一个系统例如像的Zendesk用于这一目的? 我知道这是可能以某种方式整合,例如与吉拉Hipchat,使与客户聊天功能,但吉拉太复杂,客户服务来处理? 什么是你的经验?

Answer 1:

我们使用吉拉的客户支持,但我们发现,吉拉是缺少许多必须具备所需要这个功能。 这就是为什么我们做了许多变化。

总括而言,我们很高兴与我们的选择,我们管理使用,而不是其他的解决方案吉拉节省了很多钱。

以下是我们做,这会告诉你缺什么,而在另一方面告诉你,用编程的一点点,吉拉可以做任何事情的重大变化:)

注:以下writen脚本应该重视工作流程的转变。 这些脚本编写使用Jython ,所以它需要安装使用它。

创建电子邮件问题

吉拉只发送电子邮件给吉拉用户。 因为我们不希望创建为每个处理的支持人员用户,我们使用匿名用户来代替,并使用脚本向用户发送电子邮件。

首先,设置吉拉来创建电子邮件问题 。 比,使用脚本运行pluging客户的电子邮件地址和名称保存到自定义字段。 。 码:

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通知

使用下面的脚本发送邮件:

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小时的通知

  • 创建一个名为“开放以来”自定义字段 - 一个“日期时间”字段来保存这个问题已经被打开的时间。
  • 创建一个名为“通知”的自定义字段 - 只读文本字段。
  • 使用脚本运行pluging ,我创建了一个后功能,把它放在每个转换要“打开”状态。 这是保持开放的问题时。

代码:

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
  • 最后-我用吉拉远程API -在XML-RPC方法来写定为每5分钟运行一个python脚本。 该脚本读取所有从过滤器已发行,翻出所有的人都认为有一个“打开”状态超过24小时/ 36小时/ 48小时,发送提醒邮件,并将其标记为通知,所以每种类型的只有一个提醒将被发送。

在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')

这种方法的优点主要是它的高度可定制的,并且将数据保存到自定义字段可以很容易地创建过滤器和报告,以显示已打开的时间长的问题。

升级给开发团队

创建一个新的转变- Escalate 。 这将为开发团队的问题,并链接新问题,以支持问题。 添加以下职位功能:

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)

移动销售

reate新的过渡- Move to sales 。 许多支持电话最终成为一个销售电话,这将问题转移到销售团队。 添加以下职位功能:

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 for bug tracking and customer support?