Skip Navigation LinksALVAO 10.4Rozšiřující modulyALVAO Service Desk Custom AppsAplikaceAutomatické akce na základě událostí na požadavku
Skip Navigation Links.
%USERPROFILE%\source\repos\ALVAO\Documentation\DocCs\modules\alvao_sd_custom_apps\applications\ticket_custom_actions_by_events.aspx
|
Automatické akce na základě událostí na požadavku
Automatické akce se mohou spouštět v těchto případech:
- Změna hodnoty položky požadavku (vlastní/systémová)
- Založení nového požadavku
- Vytvoření nové události
- Úprava události
- Odstranění události
- Načtení nové zprávy ze schránky služby
Upozornění:
Špatnou definicí automatické akce může být nenávratně poškozena databáze
ALVAO, proto vytváření a testování vždy provádějte na kopii databáze v
testovacím prostředí.
Příprava nové automatické akce
V aplikaci vytvořte nový skript podle šablony ITicketAutoAction resp. IActAutoAction a vhodně jej pojmenujte podle funkčnosti, kterou akce provádí.
V nově vytvořeném skriptu nastavte v konstruktoru třídy akce hodnotu vlastnosti name (název automatické akce).
Pro uložení vlastností a nastavení akce doporučujeme definovat třídu Settings v samostatném skriptu, který vytvoříte ze šablony Knihovna tříd, např.:
public static class Settings {
public const string ActionName = "Vyřešeno ve verzi – předat do testu";
public const string ServiceName = "Programové úpravy"; // Název služby, ve které má být požadavek, aby se mohl předat testerům (příklad Akce prováděné při změně položky požadavku)
public const int ControlStateId = 1; // ID stavu, ve kterém má být požadavek, aby se mohl předat testerům (příklad Akce prováděné při změně položky požadavku)
public const string SolverGroupName = "Testeři";
}
Příklad
Definice třídy:
…
class AssignToTester : ITicketAutoAction
{
public string name;
public string Name
{
get { return name; }
set { name = value; }
}
public AssignToTester()
{
name = Settings.ActionName;
}
}
…
Definice podmínek a vykonávaných operací pro automatickou akci
Upozornění:
Pokud v rámci automatické akce chcete použít jen některé z metod
implementovaného rozhraní, tak v těle ostatních metod z rozhraní vraťte
výjimku
NotImplementedException. Například takto:
public void OnTicketChanged(SqlConnection con, SqlTransaction trans, int
ticketId, int personId, string properties)
{
throw new NotImplementedException();
}
Akce prováděné při změně položky požadavku
Automatické akce je možné vykonávat při změně těchto položek:
tabulka.sloupec
|
Položka požadavku
|
tHdTicket.TicketStateId
|
Stav
|
tHdTicket.liHdTicketSlaId
|
SLA
|
tHdTicket.dHdTicketDeadline
|
Termín
|
tHdTicket.liHdTicketHdSectionId
|
Služba
|
tHdTicket.iHdTicketUser
|
Žadatel |
tHdTicket.liHdTicketSolverPersonId
|
Řešitel
|
tHdTicket.sHdTicket
|
Název požadavku
|
tHdTicket.liHdTicketPriorityId
|
Priorita
|
tHdTicket.Impact
|
Dopad
|
tHdTicket.Urgency
|
Naléhavost
|
tHdTicket.mHdTicketNotice
|
Poznámky |
tHdTicket.sHdTicketGroup
|
Skupina
|
tHdTicket.sHdTicketDeviceCode
|
Číslo zařízení
|
tHdTicket.FeedbackSolveSpeed
|
Rychlost řešení
|
tHdTicket.FeedbackProfessionality
|
Profesionalita
|
tHdTicket.FeedbackExpertise
|
Odbornost
|
tHdTicket.FeedbackComment
|
Komentáře a poznámky
|
tHdTicket.RelatedAccountId
|
Související organizace
|
tHdTicket.Objects
|
Objekty |
tHdTicket.RequestedForPersonId
|
Požadováno pro |
tHdTicketCust.*
|
Vlastní položky |
Ve vytvořené třídě akce implementujte rozhraní ITicketAutoAction a z něho metodu OnTicketChanged. Vstupními parametry jsou:
- ticketId (číslo požadavku),
- personId (id osoby, která provedla událost na požadavku) – V některých
případech mohl být systém, pak je hodnota NULL,
- properties (změněné položky požadavku oddělené čárkou – tabulka.sloupec).
V implementované metodě definujte jak podmínky pro vykonání operací, tak
samotné operace s požadavkem.
Příklad automatické akce při změně položky požadavku:
Předání požadavku řešiteli ze skupiny Testeři v případě, že
požadavek je ve službě Programové úpravy a ve stavu s id 1.
…
class AssignToTester : ITicketAutoAction
{
…
public void OnTicketChanged(SqlConnection con,
SqlTransaction trans, int ticketId, int personId, string properties)
{
if
(properties.Contains("tHdTicketCust.solvedInVersion"))
{
try
{
HelpdeskWebService sdws = new HelpdeskWebService();
// nacteni hodnot
string solvedInVersion = sdws.ReadColumn(ticketId, "tHdTicketCust",
"solvedInVersion");
string section = sdws.ReadColumn(ticketId, "TicketForeignKeyInfo",
"SectionName");
int stateId = sdws.ReadColumn(ticketId, "tHdTicket", "TicketStateId");
// kontrola hodnot
if (!String.IsNullOrEmpty(solvedInVersion) && section == Settings.ServiceName && stateId == Settings.ControlStateId)
{
// nacteni dat
using (SqlCommand Cmd = new SqlCommand($@"SELECT TOP 1 TRP.liRolePersonPersonId
newSolverId
FROM tRolePerson TRP JOIN tRole TR ON TRP.liRolePersonRoleId=TR.iRoleId WHERE
TR.sRole = N'{Settings.SolverGroupName}'", con, trans))
{
using(SqlDataReader reader = Cmd.ExecuteReader())
{
int? newSolverId; // id noveho resitele pozadavku
if (reader.Read())
{
newSolverId =
int.Parse((reader["newSolverId"]).ToString());
}
reader.Close();
// predani resiteli
if(newSolverId.HasValue)
Ticket.ChangeSolver(ticketId, newSolverId, new HtmlTextModel(string.Empty));
}
}
}
}
catch (Exception ex)
{
throw ex;
}
}
}
…
}
…
Celý příklad ke stažení: Example_AssignToTester.zip
Pro spuštění příkladu se předpokládá přidání vlastní položky solvedInVersion typu nvarchar do tabulky tHdTicketCust.
Akce prováděné při založení nového požadavku
Ve vytvořené třídě automatické akce implementujte rozhraní ITicketAutoAction a z něho metodu OnTicketCreated. Vstupními parametry jsou:
- ticketId (číslo požadavku),
- personId (id osoby, která požadavek založila – nemusí být vždy žadatel).
Příklad automatické akce při založení nového požadavku:
Při založení nového požadavku ve službě Programové úpravy je zároveň založen
navázaný požadavek ve službě Programové
úpravy/Návrhy a analýzy pro tvorbu návrhu k
založenému požadavku.
…
class AssignToTester : ITicketAutoAction
{
…
public void OnTicketCreated(SqlConnection con,
SqlTransaction trans, int ticketId, int personId)
{
try
{
HelpdeskWebService sdws = new HelpdeskWebService();
// nacteni hodnot
bool createAnalysis;
if ((sdws.ReadColumn(ticketId, "tHdTicketCust", "createAnalysis")) != null)
createAnalysis = bool.Parse(sdws.ReadColumn(ticketId, "tHdTicketCust",
"createAnalysis"));
else
createAnalysis = false;
int? analysisServiceId = null;
using (SqlCommand Cmd = new SqlCommand($@"SELECT iHdSectionId from tHdSection where sHdSection = @sectionName", con, trans))
{
Cmd.Parameters.Add("@sectionName", SqlDbType.NVarChar).Value = Settings.AnalysisServiceName;
using (SqlDataReader reader = Cmd.ExecuteReader())
{
if (reader.Read())
{
analysisServiceId = int.Parse((reader["iHdSectionId"]).ToString());
}
}
}
string section = sdws.ReadColumn(ticketId, "TicketForeignKeyInfo", "SectionName");
string name = sdws.ReadColumn(ticketId, "tHdTicket", "sHdTicket");
// kontrola hodnot
if (section == Settings.ServiceName && createAnalysis)
{
// založení požadavku na vytvoreni navrhu
var newTicketModel = new NewTicketModel();
newTicketModel.Ticket.sHdTicket = name + " - návrh";
newTicketModel.Ticket.liHdTicketUserPersonId = personId;
newTicketModel.LoadRequesterData = true;
newTicketModel.Ticket.liHdTicketHdSectionId = analysisServiceId.Value;
var ticket = Ticket.Create(newTicketModel);
int newTicketId = ticket.iHdTicketId;
// vytvoreni vazby
Relation.Create(ticketId, newTicketId, 2, Person.GetSystem().iPersonId);
}
}
catch (Exception ex)
{
throw ex;
}
}
…
}
…
Celý příklad ke stažení: Example_CreateAnalysis.zip
Pro spuštění příkladu se předpokládá přidání vlastní položky solvedInVersion typu nvarchar do tabulky tHdTicketCust.
Akce prováděné při vytvoření události
Automatické akce je možné vykonat při těchto
situacích:
- Ruční vytvoření libovolné události příkazem Nová událost nebo Poznámka.
- Odeslání zprávy příkazem Poslat zprávu, Odpovědět, atd.
- Načtení e-mailu ze schránky služby aplikací MailboxReader.
- Ruční načtení zprávy z Outlooku pomocí Outlook Add-in - Uložit do deníku požadavku.
- Vytvoření zakládající události při vzniku nového požadavku.
- Zavoláním webové metody CreateAct, případně CreateTicket, kde se vytváří
zakládající zpráva.
Ve vytvořené třídě automatické akce implementujte rozhraní IActAutoAction a z něho metodu OnActCreated. Vstupními parametry jsou:
- actId (id události),
- personId (id osoby, která událost vytvořila).
Příklad automatické akce při vytvoření události:
Při vytvoření události v některém požadavku ve službě Programové
úpravy je tato událost přeposlána v e-mailu každému manažerovi služby,
pokud není autorem ani příjemcem události.
…
class SendMailsAboutNewEvent : IActAutoAction
{
public string name;
public string Name
{
get { return name; }
set { name = value; }
}
public SendMailsAboutNewEvent()
{
name = Settings.ActionName;
}
public void OnActChanged(SqlConnection con, SqlTransaction trans, int
actId, int personId, string properties) {
throw new NotImplementedException();
}
public void OnActRemoved(SqlConnection con, SqlTransaction trans, int
actId, int personId) {
throw new NotImplementedException();
}
public void OnActCreated(SqlConnection con, SqlTransaction trans, int actId,
int personId)
{
try
{
// nacteni hodnot
int ticketId = 0, fromPersonId = 0, sectionId = 0;
string actFrom = "", actFromEmail = "", actTo = "", actToEmail = "",
actSubject = "", actPlainText = "", sectionName = "", sectionEmail = "";
using (SqlCommand Cmd = new SqlCommand(@"SELECT liActHdTicketId,
liActFromPersonId, sActFrom, sActFromEmail,
sActTo, sActToEmail, sAct, mActNotice, sHdSection, sHdSectionEmail, iHdSectionId FROM tAct a
join tHdTicket t on a.liActHdTicketId=t.iHdTicketId
join tHdSection s on t.liHdTicketHdSectionId=s.iHdSectionId WHERE iActId =
@actId", con, trans))
{
Cmd.Parameters.Add("@actId", SqlDbType.Int).Value = actId;
using (SqlDataReader reader = Cmd.ExecuteReader())
{
if (reader.Read())
{
ticketId =
int.Parse((reader["liActHdTicketId"]).ToString());
fromPersonId =
int.Parse((reader["liActFromPersonId"]).ToString());
actFrom = (reader["sActFrom"]).ToString();
actFromEmail = (reader["sActFromEmail"]).ToString();
actTo = (reader["sActTo"]).ToString();
actToEmail = (reader["sActToEmail"]).ToString();
actSubject = (reader["sAct"]).ToString();
actPlainText = "Dobrý den,\n\n na požadavku číslo " +
ticketId.ToString() + " byla vytvořena událost:\n\n" +
(reader["mActNotice"]).ToString();
sectionName = reader["sHdSection"] as string;
sectionEmail = reader["sHdSectionEmail"] as string;
sectionId = int.Parse((reader["iHdSectionId"]).ToString());
}
reader.Close();
}
}
// kontrola hodnot
if (sectionName == Settings.ServiceName)
{
List<string> recipients = new List<string>();
using (SqlCommand Cmd = new SqlCommand(@"select sPersonEmail from HdSectionManager
left join tPerson on iPersonId = PersonId
where sPersonEmail is not null and HdSectionId = @sectionId", con, trans))
{
Cmd.Parameters.Add("@sectionId", SqlDbType.Int).Value =
sectionId;
using (SqlDataReader reader = Cmd.ExecuteReader())
{
string personEmail = "";
while (reader.Read())
{
personEmail = (reader["sPersonEmail"]).ToString();
if (!actTo.Contains(personEmail) &&
!actToEmail.Contains(personEmail) && !actFrom.Contains(personEmail) &&
!actFromEmail.Contains(personEmail))
recipients.Add(personEmail);
}
reader.Close();
}
}
//odeslani e-mailu
if (recipients.Count > 0)
{
string to = String.Join(";", recipients);
string from = sectionEmail;
string subject = actSubject;
string body = actPlainText;
System.Net.Mail.MailMessage message = new MailMessage(from, to, subject, body);
Alvao.API.Common.Email.QueueMailMessage(message);
}
}
}
catch (Exception ex)
{
throw ex;
}
}
}
…
Celý příklad ke stažení: Example_SendMailsAboutNewEvent.zip
Akce prováděné při úpravě události
Automatické akce je možné vykonat při změně těchto položek:
tabulka.sloupec |
Položka události |
tAct.dAct |
Datum |
tAct.liActKindId |
Komu |
tAct.sActTo |
Datum |
tAct.sAct |
Předmět |
tAct.mActNotice |
Text |
tDocument.liDocumentActId |
Přílohy |
tActHd.bActHdUserRead |
Zobrazit žadateli |
tAct.bWaitingForUser |
Čekání na žadatele |
tAct.nActWorkHours |
Práce |
tAct.nActTravelHours |
Čas na cestě |
tAct.nActTravelKm |
Vzdálenost |
tAct.bNoCharge |
Nefakturovat |
Ve vytvořené třídě automatické akce implementujte rozhraní IActAutoAction a z něho metodu OnActChanged. Vstupními parametry jsou:
- actId (id události),
- personId (id osoby, která událost změnila),
- properties (změněné položky události, oddělené čárkou – tabulka.sloupec).
Akce prováděné při odstranění události
Automatické akce je možné vykonat při odstranění
všech zpráv a událostí.
Ve vytvořené třídě automatické akce implementujte rozhraní IActAutoAction a z něho metodu OnActRemoved. Vstupními parametry jsou:
- actId (id události),
- personId (id osoby, která událost odstranila).
Akce prováděné při načtení zprávy
Automatické akce je možné vykonat při
načtení zprávy ze schránky služby ještě před uložením zprávy do deníku již
existujícího požadavku, resp. před vytvořením nového požadavku.
Ve vytvořené třídě automatické akce implementujte rozhraní IMailMessageAutoAction a z něho metodu OnMessageReceived. Vstupními parametry jsou:
- message (objekt se zprávou),
- sectionId (id služby, ve které byla zpráva načtena),
- ticketId (id požadavku, ke kterému zpráva podle předmětu patří, resp.
nula, pokud se jedná o vytvoření nového požadavku),
- fromPersonId (id odesílatele zprávy, resp. účtu Host, pokud
odesílatel zprávy nebyl mezi uživateli nalezen).
Z metody OnMessageReceived
vraťte návratovou hodnotu true nebo false
určující, zda se má zpráva dále standardně
zpracovávat nebo ne.
Pokud je těchto automatických akcí implementováno více, volají se postupně
do té doby, dokud některá nevrátí hodnotu false,
přičemž není garantováno pořadí jejich volání.
Poznámka:
Pokud není zpráva po automatických akcích dále zpracována, do protokolu
událostí je o tom zapsáno varování.
Příklad automatické akce při načtení zprávy:
Při načtení zprávy se u
existujících požadavků zkoumá text zprávy, zda neobsahuje příkaz pro předání
řešiteli „ASSIGNTO: jméno řešitele“. Pokud jej obsahuje a řešitel je podle jména
nalezen, požadavek se mu automaticky předá a zpráva nebude zaznamenána do deníku
požadavku. Jinak je zpráva zpracována standardním způsobem.
……
public class AssignToSolverByEmail : IMailMessageAutoAction
{
public string name;
public string Name
{
get { return name; }
set { name = value; }
}
public AssignToSolverByEmail()
{
name = Settings.ActionName;
}
public bool OnMessageReceived(SqlConnection con, SqlTransaction trans,
Rebex.Mail.MailMessage message, int sectionId, int ticketId, int fromPersonId)
{
if (ticketId == 0)
return true;
if(message.BodyText != null)
{
int startIndex = message.BodyText.IndexOf("ASSIGNTO:");
if(startIndex >= 0)
{
int length = message.BodyText.IndexOf("\n", startIndex) -
(startIndex + 9);
string user = message.BodyText.Substring(startIndex + 9,
length).Trim();
int? solverId = null;
using (SqlCommand Cmd = new SqlCommand(@"exec spPersonSearch
@sample, NULL, 0, NULL, '', 1", con, trans))
{
Cmd.Parameters.Add("@sample", SqlDbType.NVarChar).Value =
user;
using (SqlDataReader reader = Cmd.ExecuteReader())
{
if (reader.Read())
{
solverId = reader["PersonId"] as int?;
}
}
if(solverId.HasValue){
Alvao.API.SD.Ticket.ChangeSolver(ticketId, solverId, new API.Common.Model.HtmlTextModel(string.Empty), null, fromPersonId);
return false;
}
}
}
}
return true;
}
}
…
Celý příklad ke stažení: Example_AssignToSolverByEmail.zip
Akce prováděné při schvalování
V průběhu schvalování můžete spouštět automatické akce na základě těchto událostí:
- Schválení požadavku
- Zamítnutí požadavku
- Přidání schvalovatele do schvalování
- Zrušení konkrétního schvalovatele
Automatické akce jsou volány pouze pro ručně spouštěná schvalování s vypnutým automatickým přechodem do dalšího stavu.
V aplikaci vytvořte nový skript podle šablony ITicketApprovalAutoAction a vhodně jej pojmenujte podle funkčnosti, kterou akce provádí. Vstupními parametry metod jsou:
Příklad automatické akce při schvalování
Při schválení požadavku ve službě Nákup všemi schvalovateli přechází požadavek do stavu Objednávka.
public class OrderAfterApprovalTicketApprovalAutoAction : ITicketApprovalAutoAction
{
public string Name
{
get => Settings.ActionName;
set => Name = value;
}
public void OnApproved(SqlConnection con, SqlTransaction trans, int ticketId, int approvalItemId)
{
HelpdeskWebService sdws = new HelpdeskWebService();
string sectionName = sdws.ReadColumn(ticketId, "TicketForeignKeyInfo", "SectionName");
string stateName = Alvao.API.SD.TicketState.GetCurrentStateByTicketId(ticketId)._TicketState;
// Informace o schválení (schvalovatel, komentář apod.)
tHdTicketApprovalItem currentApprovalItem = Alvao.API.SD.Approval.GetApprovalItemById(approvalItemId);
if(sectionName == Settings.ServiceName && stateName == Settings.State)
{
// Vrátí seznam schvalovatelů aktuálního schvalování, včetně jejich rozhodnutí.
IEnumerable<tHdTicketApprovalItem> approvalItems = Alvao.API.SD.Approval.GetCurrentApprovalItems(ticketId);
// Pokud všichni schválili
if(approvalItems.Where(s => s.liHdTicketApprovalItemHdTicketApprovalItemResultId == (int)tHdTicketApprovalItem.ApprovalResult.Accepted).Count() == approvalItems.Count())
{
Alvao.API.Common.Model.Database.TicketState targetState = Alvao.API.SD.TicketState.GetByName(Settings.TargetState, ticketId);
if(targetState == null)
return;
int systemPersonId = Alvao.API.Common.Person.GetSystem().iPersonId;
// Změna stavu
Alvao.API.SD.Ticket.ChangeState(ticketId, targetState.id, systemPersonId, null);
}
}
}
...
}
Celý příklad ke stažení: Example_TicketApprovalAutoAction.zip
Odeslání zprávy v rámci automatické akce
Pokud potřebujete v rámci automatické akce odeslat libovolnou zprávu,
využijte k tomu metodu SendMessage. Pokud si nepřejete, aby odeslaná zpráva byla zapsána do deníku požadavku, využijte metodu QueueMailMessage.
Poznámka:
Metody mohou být využity i pro ostatní typy rozšíření.
Nenašli jste co jste hledali? Zeptejte se našeho týmu technické podpory.
|