2013-03-07 4 views
6

私たちはJiraをバグ追跡に使用し、Gitと統合してバグ修正とバージョニング処理を結びつけることを考えています。バグトラッキングとカスタマーサポートのためのJira?

お客様サポートにもJiraをお勧めしますか?その目的のためにZendeskのような別のシステムを見つけるべきですか?顧客とのチャット機能を可能にするためにHipchatとJiraを統合することは何とか可能ですが、Jiraは扱いにくいですか?あなたの経験は何ですか?

+0

優秀な質問 - 私も答えを見るのが好きです。 – Brandon

答えて

14

私たちは顧客サポートにJiraを使用していますが、Jiraにはこれに必要な多くの必須機能がないことがわかりました。そういうわけで私たちは多くの変更を行います。

私たちは私たちの選択に非常に満足しています。他のソリューションの代わりにJiraを使用することで、たくさんのお金を節約することができました。ここで

あなたがプログラミングの少しで、JIRAが何かを行うことができますが、他の手のショーで、これが欠けているものを紹介します、私たちが作った主な変更点です:)

注:スクリプト以下の記述はワークフローの移行に付くべきです。スクリプトはJythonを使用して記述されているため、インストールする必要があります。

JIRAが唯一のJIRAユーザーに電子メールを送信し、電子メールで

を問題を作成します。サポートに取り組むすべてのユーザーのユーザーを作成したくないため、代わりに匿名ユーザーを使用し、スクリプトを使用して電子メールを送信しました。

まず、Jiraをcreate issues from emailsに設定します。 [Script Runner 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 protected]>] 
     # 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 protected]] 
     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通知に

を送る次のスクリプトを使用してメールを送信:new_case.template

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._%+-][email protected](?:[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 = '[email protected]' 
    subject = "["+key+"] Thank You for Contacting Support team" 
    mail_user = '[email protected]' 
    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) 

内容:

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 

はISS UEリマインダ - 問題が開かれた時間を保持するために「日付時刻」欄 - 24/36/48時間の通知「オープン以来」というカスタムフィールドを作成し

  • のためのオープン。
  • 読み取り専用のテキストフィールドである「通知」というカスタムフィールドが作成されました。
  • Script Runner plugingを使用して、私はポスト関数を作成し、 'Open'状態に移行するたびにそれを配置しました。これは問題の開始時間を維持するためです。

コード:

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 remote API - XML-RPCメソッドを使用して、5分ごとに実行するようにスケジュールされたpythonスクリプトを作成しました。スクリプト は、フィルタから発行されたすべてのものを読み込み、24時間36時間48時間以上開いている状態のすべてをプルし、通知電子メールを送信し、通知されたものとしてマークするので、各タイプの通知は1つだけになります送信されます。

の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 = '[email protected]' 
mail_user = '[email protected]' 
mail_password = 'password' 
toAddr = '[email protected]' 
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 - 開発チームに

エスカレート

は、新しいトランジションを作成します。これにより、開発チームに問題が発生し、新しい問題がサポートの問題にリンクされます。 Move to salesから

は、新たな移行をreate

に販売への移行

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) 

次のポスト機能を追加します。サポートコールの多くはセールスコールとして終了し、問題をセールスチームに移します。次の投稿機能を追加してください:

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) 
+0

ありがとう!私はあなたの答えにとても満足しています! – user2144454

関連する問題