📜 ⬆️ ⬇️

Customization of workflows in YouTrack. My experience tweaking YouTrack as HelpDesk

I would like to tell you about my experience of setting “YouTrack as HelpDesk” .

Following the link that I indicated above, you will find more or less detailed instructions on how to deploy YouTrack from scratch and perform its initial configuration. In the case when HelpDesk is built to handle requests in a large company, the development of its Workflow is inevitable.

1. We register the appeal, we form auto-responses


I work in a company that provides its services to banks. Until a certain time, we used a self-help HelpDesk and it was poor. At a certain time there was a question about his replacement. At the same time, this relocation should have been minimal / noticeable for bank employees.

The first thing I had to deal with was the registration of new calls and sending auto-answers to them.
')
With registration everything is simple, we add SMTP, we add a box and a filtering rule in the email integration settings. With auto answer more interesting. Initially, I had the “Send notifications to unregistered users” rule in the notifyUnregisteredUsers process. Its essence boiled down to the rule “When a comment is added - send”. However, this rule is suitable for us only to send a response to the bank, when we wrote it ourselves in a comment.

As a solution, the following rule was written:

rule notification about created issue when becomesReported() { ..... if (Customer email != null) { sendMail(Customer email, "Autoreply:" + " [" + getId() + "] " + issue.summary, "       \" \",     : [" + getId() + "]<br> : " + now.format(mediumDateTime) + "<br>      . <br><br> , ....  ..") } } 

The condition when becomes Report () always works BEFORE the publication of a new issue. This is how the auto answer is solved.
The next question was how to send an auto answer when adding a bank comment (i.e., an answer to the supporter’s answer). As a solution to the corrected Send notifications to unregistered users:

 when comments.added.isNotEmpty { ...... //  Last comment author  null,    if (Last comment author != null) { sendMail(Last comment author, "Autoreply:" + " [" + getId() + "] " + issue.summary, "   c    \" \"        : [" + getId() + "]<br> : " + now.format(mediumDateTime) + "<br>      . <br><br> , c ....."); } ....... Last comment author = null; } 

Last comment author is a technical field, it is necessary in order to understand who wrote the bank or supporter. In the post-processing rule, we specified “Last comment author $ {from}” which means “Set the value of the Last comment author field as the email sender of the letter”.
And at the end of the rule, we always set it as null. Therefore, the bank wrote - send an auto answer, otherwise do not send.

2. Filling in custom fields


In addition to communication letters, we needed to collect information on the status of the task, who owns, how many letters on the task went. For these purposes, we created our own task fields such as Type, Criticality, Number of Bank Letters, Polygon, Release, Deadline, Bank Closing Date, and so on.

A good half of them were filled in with Workflow. Below is an example of filling in the deadline and determining the bank by mail domain:

 when becomesReported() { ..... //        issue.deadline = now + 24 hours; if (issue.deadline.format(#e) == 6) { issue.deadline = issue.deadline + 48 hours; } if (issue.deadline.format(#e) == 7) { issue.deadline = issue.deadline + 24 hours; } ..... //     var bank = ""; var ce = ""; ce = issue.Customer email + "~"; bank = ce.substringBetween("@", "~"); if (issue. == null) { if (bank == "somebank.domain.com") { issue. = {- }; } ....... } } 

I will a little explain the code. issue. {something} is a custom task field. It is displayed in the project. And you can also omit the “issue.” So that the issue. Customer email and Customer email are one and the same. But the var bank = ""; just a local variable.

Here is the rule that closes the task yourself:

 rule CloseFromBankRequest when issue.hasTag(" ") { if (issue.hasTag(" ")) { debug("   " + issue.getId()); if (issue.Type == {Bug}) { //   ,          if (issue.desc == null) { issue.desc = issue.summary; } if (issue.solution == null) { issue.solution = "  "; } issue.ballis = {}; issue.polygon = {}; issue.causer = {}; if (issue. == null) { issue. = { }; } issue.Timer = {}; } else { if (issue.desc == null) { issue.desc = issue.description; } if (issue. == null) { issue. = { }; } issue.ballis = {}; issue.Timer = {}; } } } 

when issue.hasTag - when added a tag.

I use this rule like this. Implemented its own web-interface, in which the list of tasks of the bank is transmitted via api. Clicking on the "Close" button again, via api YouTrack put the tag. With this tag, Workflow closes the task itself, sets the required fields itself.

3. Just a couple of examples.


Task closure notification:

 rule VoteCloseIssues when issue..changed { if (issue. == {Fixed} && (issue.Type == {Bug} || issue.Type == {Task})) { var preview = " . <br><br>  ,     [" + getId() + "] . <br>    ,    <a href=\"mailto:support@bifit.ua?subject=[" + getId() + "] " + summary + "&body= \"></a>     . <br><br>      ? <br><a href=\"http://{link_to_web_interface}/report/Issues.php?api=vote&id=" + getId() + "&mark=good\">,  </a><br><a href=\"http://{link_to_web_interface}/report/Issues.php?api=vote&id=" + getId() + "&mark=bad\">,  </a><br><br>  :<br><br>"; var i = 0; var author_comment = ""; var subj_comment = "    [" + getId() + "]"; var text_comment = ""; var date_comment = now.format(mediumDateTime); var full_text = ""; while (issue.comments[i].text != null || i < 10) { author_comment = issue.comments[i].author.fullName; date_comment = issue.comments[i].created.format(mediumDateTime); text_comment = wikify(issue.comments[i].text); //    if (issue.comments[i].permittedGroup == null && issue.comments[i].text != null) { full_text = "<b>" + author_comment + ":</b><br> : " + date_comment + "<br><blockquote>" + text_comment + "</blockquote><br><hr><br><br>" + full_text; } i = i + 1; } full_text = full_text + "<b>" + ":</b><br> : " + issue.created.format(mediumDateTime) + "<br><blockquote>" + wikify(issue.description) + "</blockquote><br><hr><br><br>"; full_text = preview + full_text; sendMail(Customer email, subj_comment, full_text); } } 

Here I will explain a little.

 when issue..changed 
When changed the value of the field "Status".
 if (issue. == {Fixed} && (issue.Type == {Bug} || issue.Type == {Task})) 
If the status is “Closed” and the task type is “Bug” or “Consultation”.
 preview 
The beginning of the text of the letter. There is a notification about closing the task, links to the assessment (the same web interface and api).
 while (issue.comments[i].text != null || i < 10) 
Let's go through the last 10 comments and add the author, the text of the comment in full_text (this is the history of correspondence)
 full_text = full_text + "<b>" + ":</b><br> : " + issue.created.format(mediumDateTime) + "<br><blockquote>" + wikify(issue.description) + "</blockquote><br><hr><br><br>"; 
In the history, the most recent comment will be the first appeal of the bank wikify (issue.description)
 sendMail(Customer email, subj_comment, full_text); 
Send all this to the bank.

Fill the subsystem automatically if a specific type of integration module is selected:

 rule set_subsystem_if_change_gateway when issue. .changed { if (issue.Subsystem != { } && issue.  != null) { issue.Subsystem = { }; } } 

We check if we have gone beyond the deadline (timed tasks):

 schedule rule check deadline every minute [issue.Timer != {} || issue. == {Fixed}] { if (issue.deadline == null || issue. == {Fixed} || issue.ballis == {}) { //               ,  if (issue.hasTag("")) { issue.applyCommand("  "); } // ,    } else if (issue.deadline <= now) { //      ,  ""     if (issue.hasTag("")) { if (issue.hasTag("")) { issue.applyCommand("  "); if (issue.isoverdue == {}) { issue.isoverdue = null; } } //  (  ) } else { if (!issue.hasTag("")) { issue.applyCommand("  "); if (issue.isoverdue == null) { issue.isoverdue = {}; } } } } } 


If we forget to stop the task and go home, YouTrack will do it for you:

 schedule rule pause all issues in overtime daily at 18:15:00 [issue.Timer == { }] { issue.Timer = {}; } 


Well that's all. I hope my publication will someday help.

Write questions / comments in comments or private messages.

Source: https://habr.com/ru/post/247939/


All Articles