Re: [otrs] Master Ticket Documentation

Michiel Beijen wrote:
Have you read the thread called 'enable Master/Slave ticket feature' from this week? and also the youtube vid: http://www.youtube.com/watch?v=zkc_qTCSloo
Just did now. While creating a Master seems easy, the process to make a Master after the fact is pretty convoluted! The video did help me understand the purpose.
You should still create 21 tickets of course, but they can be created very fast and linked to the master ticket. You can send out emails and close the child tickets from the master.
If you'd want to create tickets even faster, you could look into using Ticket Templates: http://www.jbothe.de/blog/?p=130
Since I don't read German, I had to use Google Translate, and to be perfectly honest, I have no clue what his Blog Entry is attempting to explain. I _THINK_ what he's adding is some buttons at the top of the page that set a few of the page variables so that you don't have to fill that in each time for a commonly recurring ticket response. I see the value in that. Still, this seems to be the recommended course of action: 1. Create a Master Ticket 2. Create 21 Slave Tickets (Phone?) 3. Send an email to the Master Ticket and close it. That definitely helps the situation compared to 2.3.x. But I still have a problem with "Create 21 Slave Tickets." That's something I have to do 21 times. I have a customer database linked into OTRS, I'd like to simply provide a comma delimited list of either userIDs or email addresses, and have OTRS create a new ticket for each one. I know this can be accomplished with the API, but for this instance, creating 21 tickets seems easier than trying to learn the API and create a script. However, when 21 tickets turns into 200 or 500, ouch. I'm still shocked there is no easy way to use OTRS to proactively communicate with a bulk set of customers. Looking at the API, how would I use Kernel::System::Ticket->TicketCreate to create tickets that are associated with a Master ticket? My guess: $TicketObject->TicketFreeTextSet( Counter => 1, # Or should this be 12 as in the video? Key => 'Slave', Value => '12481', # Ticket Number of the master TicketID => '12482', # Ticket Number of the slave UserID => 123, # Is this a Kernel::System::User or a Kernel::System::CustomerUser? ); So maybe I can write something that, once I create the Master ticket, I can write a short snippet that creates the tickets and then associates them with the Master Ticket. Beckman --------------------------------------------------------------------------- Peter Beckman Internet Guy beckman@angryox.com http://www.angryox.com/ ---------------------------------------------------------------------------

So I've worked some on a bulk script. The tickets are being created, and I'm even successfully associating the tickets to the Master! Unfortunately, I'm missing something. I sent an email to the Master ticket, and no emails went out to the other Slave Tickets. In the Web UI, the Master Ticket shows "MasterTicket: Master" and shows 3 linked children, as expected. Looking at one of the slaves, it shows "MasterTicket: Slave" and Linked Parent to the correct Master. Free Fields correctly displays MasterTicket: Slave, and Link shows correctly linked Parent. Additionally, the correct Customer Info was displayed for the ticket, and the fake Phone Article I created had the correct email for the customer. Please note, this is using a config-based external Customer Database. I'm not sure if that has something to do with this, but I assume not. Here's the history for one of Slave Tickets after an email was sent to the Master Ticket: 10/09/2009 14:55:39 NewTicket New Ticket [102082813683] created (Q=Raw;P=3 normal;S=new). 10/09/2009 14:55:39 CustomerUpdate Updated: CustomerID=xxxx;CustomerUser=xxxxxxxx@xxxxxxxxxxxx; 10/09/2009 14:55:39 EmailCustomer Created by BulkTicket Script 10/09/2009 14:55:39 TicketFreeTextUpdate Updated: FreeKey12=MasterTicket;FreeText12=Slave; 10/09/2009 14:55:39 TicketLinkAdd Added link to ticket "103395832887". 10/09/2009 14:57:13 Misc MasterTicket: no customer email found, send no master message to customer. 10/09/2009 14:57:13 StateUpdate Old: "new" New: "closed successful" I see the problem, no customer email found, but where am I not setting that? The %User object returns the customers email as UserID, and that is used in both the Ticket and Article creation. Any API hackers want to help? The documentation is pretty sparse when it comes to listing and explaining all possible values for Ticket Creation. Even LinkAdd() didn't mention "Direction" nor why it was excluded, if indeed that was on purpose. The code: =========================================================================== #!/usr/bin/perl -w # -- # otrs.bulkSlaveTicketCreate # # Quickly Create multiple Slave tickets associated with a Master ticket # # Written by Peter Beckman <beckman at angryox dot com> # October 9, 2009 # -- # License: Creative Commons Attribution-Share Alike 3.0 United States License # More Info: http://creativecommons.org/licenses/by-sa/3.0/us/ # This software comes with ABSOLUTELY NO WARRANTY. # -- use File::Basename; use FindBin qw($RealBin); use lib dirname($RealBin); use lib dirname($RealBin)."/Kernel/cpan-lib"; use Data::Dumper; use Kernel::Config; use Kernel::System::Encode; use Kernel::System::Log; use Kernel::System::Time; use Kernel::System::Main; use Kernel::System::DB; use Kernel::System::Ticket; use Kernel::System::CustomerUser; use Kernel::System::User; my $ConfigObject = Kernel::Config->new(); my $EncodeObject = Kernel::System::Encode->new( ConfigObject => $ConfigObject, ); my $LogObject = Kernel::System::Log->new( ConfigObject => $ConfigObject, EncodeObject => $EncodeObject, ); my $TimeObject = Kernel::System::Time->new( LogObject => $LogObject, ConfigObject => $ConfigObject, ); my $MainObject = Kernel::System::Main->new( LogObject => $LogObject, EncodeObject => $EncodeObject, ConfigObject => $ConfigObject, ); my $DBObject = Kernel::System::DB->new( ConfigObject => $ConfigObject, EncodeObject => $EncodeObject, MainObject => $MainObject, LogObject => $LogObject, ); my $UserObject = Kernel::System::User->new( ConfigObject => $ConfigObject, LogObject => $LogObject, MainObject => $MainObject, TimeObject => $TimeObject, DBObject => $DBObject, EncodeObject => $EncodeObject, ); my $CustomerUserObject = Kernel::System::CustomerUser->new( ConfigObject => $ConfigObject, LogObject => $LogObject, DBObject => $DBObject, MainObject => $MainObject, EncodeObject => $EncodeObject, UserObject => $UserObject, ); my $TicketObject = Kernel::System::Ticket->new( ConfigObject => $ConfigObject, LogObject => $LogObject, DBObject => $DBObject, MainObject => $MainObject, TimeObject => $TimeObject, EncodeObject => $EncodeObject, CustomerUserObject => $CustomerUserObject, UserObject => $UserObject, ); my $LinkObject = Kernel::System::LinkObject->new( ConfigObject => $ConfigObject, LogObject => $LogObject, DBObject => $DBObject, TimeObject => $TimeObject, MainObject => $MainObject, EncodeObject => $EncodeObject, UserObject => $UserObject, ); print "Enter Customer emails or IDs, separated by a comma.\n"; my $userlist = &promptUser("Customer Emails/IDs"); $userlist =~ s/\s+//g; my @users = split(/,/, $userlist); my @usergroup; foreach(@users) { my %List = $CustomerUserObject->CustomerSearch( Search => "*$_*" ); if (!%List) { print "Could not find user matching $_\n"; next; } my @Foo = keys %List; my %User = $CustomerUserObject->CustomerUserDataGet( User => $Foo[0], ); print "User: " . $User{'UserFirstname'} ." UID: ". $User{'UserCustomerID'} ."\n"; push @usergroup, \%User; } my $MasterTicketID = &promptUser("Master Ticket ID"); my $UserID = &promptUser("Agent UserID (numeric)"); # remove spaces # split into an array # foreach over the motherfucker to see if they are valid. # Create multiple tickets # Send multiple articles foreach(@usergroup) { print Dumper(\$_); print "User: " . $_->{'UserFirstname'} ." UID: ". $_->{'UserCustomerID'} ."\n"; my $TicketID = $TicketObject->TicketCreate( TN => $TicketObject->TicketCreateNumber(), Queue => 'Raw', Lock => 'unlock', GroupID => 2, Priority => '3 normal', State => 'new', CustomerNo => $_->{'UserCustomerID'}, CustomerUser => $_->{'UserID'}, OwnerID => $UserID, # current owner UserID => $UserID, ); if (!$TicketID) { print "Unable to create Ticket for " . $_->{'UserCustomerID'} ."\n"; next; } print "Ticket (TicketID:$TicketID) created.\n"; # Add an article here with the From set. my $ArticleID = $TicketObject->ArticleCreate( TicketID => $TicketID, ArticleType => 'phone', # email-external|email-internal|phone|fax|... SenderType => 'customer', # agent|system|customer From => $_->{'UserFirstname'} . '<' . $_->{'UserID'} .'>', # not required but useful Subject => 'New Slave Ticket', # required Body => 'New Bulk Slave Ticket', # required ContentType => 'text/plain; charset=UTF-8', HistoryType => 'EmailCustomer', # EmailCustomer|Move|AddNote|PriorityUpdate|WebRequestCustomer|... HistoryComment => 'Created by BulkTicket Script', UserID => $UserID, ); if (!$ArticleID) { print "Unable to create Article for " . $_->{'UserCustomerID'} ."\n"; next; } print "Article (ArticleID:$ArticleID) aded to TicketID $TicketID.\n"; # Set Free Text to Slave. Not sure how to check if it worked. $TicketObject->TicketFreeTextSet( Counter => 12, # This seems to be TicketFreeText12, so use 12 here Key => "MasterTicket", Value => "Slave", TicketID => $TicketID, # The Slave TicketID UserID => $UserID, ); # Link Ticket to Master as Slave. Even though the documentation on OTRS.org sucks anus, # The ParentChild type is what we want, and we want to set the Direction as Target from the master ticket. my $True = $LinkObject->LinkAdd( SourceObject => 'Ticket', SourceKey => $MasterTicketID, # Master Ticket ID TargetObject => 'Ticket', TargetKey => $TicketID, # Slave Ticket ID Type => 'ParentChild', Direction => 'Target', State => 'Valid', UserID => $UserID, ); if (!$True) { print "Link to master failed for " . $_->{'UserCustomerID'} ."\n"; next; } # OK, at this point, we should have a new ticket with an article attached # so a Master Action will send email to all Slaves. } # Taken without permission from # http://www.devdaily.com/perl/edu/articles/pl010005/pl010005.shtml # on February 2, 2009 # modified to not be annoying about undefined values sub promptUser { local($promptString,$defaultValue) = @_; if (defined($defaultValue)) { print $promptString, "[", $defaultValue, "]: "; } else { print $promptString, ": "; } $| = 1; # force a flush after our print $_ = <STDIN>; # get the input from STDIN (presumably the keyboard) chomp; if (defined($defaultValue) and "$defaultValue") { return $_ ? $_ : $defaultValue; # return $_ if it has a value } else { return $_; } } exit (0); ======================================================================= --------------------------------------------------------------------------- Peter Beckman Internet Guy beckman@angryox.com http://www.angryox.com/ ---------------------------------------------------------------------------

Hi Peter,
I guess your script works for me... only you'd have to change
CustomerNo => $_->{'UserCustomerID'}, to CustomerID =>
$_->{'UserCustomerID'},
--
Michiel Beijen
R&D
OTRS AG
Norsk-Data-Str 1.
61352 Bad Homburg
Deutschland
T: +31 (0) 6457 42418
F: +49 (0) 9421 56818-18
I: http://www.otrs.com/
Business Location: Bad Homburg, Country Court: Bad Homburg, Commercial
register: 10751, Tax ID: 003 240
97505 Chairman of the Board: Burchard Steinbild, Managing Board: André
Mindermann (CEO), Martin Edenhofer
CU@ IIR Service Desk Forum in Mainz
(Germany)http://www.otrs.com/en/news-and-press/news-details/article/translate-to-engl...and
get to know more about OTRS at booth no. 12 from Nov 24-25, 2009!
On Fri, Oct 9, 2009 at 9:23 PM, Peter Beckman
So I've worked some on a bulk script. The tickets are being created, and I'm even successfully associating the tickets to the Master!
Unfortunately, I'm missing something. I sent an email to the Master ticket, and no emails went out to the other Slave Tickets.
In the Web UI, the Master Ticket shows "MasterTicket: Master" and shows 3 linked children, as expected. Looking at one of the slaves, it shows "MasterTicket: Slave" and Linked Parent to the correct Master.
Free Fields correctly displays MasterTicket: Slave, and Link shows correctly linked Parent.
Additionally, the correct Customer Info was displayed for the ticket, and the fake Phone Article I created had the correct email for the customer. Please note, this is using a config-based external Customer Database. I'm not sure if that has something to do with this, but I assume not.
Here's the history for one of Slave Tickets after an email was sent to the Master Ticket:
10/09/2009 14:55:39 NewTicket New Ticket [102082813683] created (Q=Raw;P=3 normal;S=new). 10/09/2009 14:55:39 CustomerUpdate Updated: CustomerID=xxxx;CustomerUser=xxxxxxxx@xxxxxxxxxxxx; 10/09/2009 14:55:39 EmailCustomer Created by BulkTicket Script 10/09/2009 14:55:39 TicketFreeTextUpdate Updated: FreeKey12=MasterTicket;FreeText12=Slave; 10/09/2009 14:55:39 TicketLinkAdd Added link to ticket "103395832887". 10/09/2009 14:57:13 Misc MasterTicket: no customer email found, send no master message to customer. 10/09/2009 14:57:13 StateUpdate Old: "new" New: "closed successful"
I see the problem, no customer email found, but where am I not setting that? The %User object returns the customers email as UserID, and that is used in both the Ticket and Article creation.
Any API hackers want to help? The documentation is pretty sparse when it comes to listing and explaining all possible values for Ticket Creation. Even LinkAdd() didn't mention "Direction" nor why it was excluded, if indeed that was on purpose.
The code:
===========================================================================
#!/usr/bin/perl -w # -- # otrs.bulkSlaveTicketCreate # # Quickly Create multiple Slave tickets associated with a Master ticket # # Written by Peter Beckman <beckman at angryox dot com> # October 9, 2009 # -- # License: Creative Commons Attribution-Share Alike 3.0 United States License # More Info: http://creativecommons.org/licenses/by-sa/3.0/us/ # This software comes with ABSOLUTELY NO WARRANTY. # --
use File::Basename; use FindBin qw($RealBin); use lib dirname($RealBin); use lib dirname($RealBin)."/Kernel/cpan-lib"; use Data::Dumper;
use Kernel::Config; use Kernel::System::Encode; use Kernel::System::Log; use Kernel::System::Time; use Kernel::System::Main; use Kernel::System::DB; use Kernel::System::Ticket; use Kernel::System::CustomerUser; use Kernel::System::User;
my $ConfigObject = Kernel::Config->new();
my $EncodeObject = Kernel::System::Encode->new( ConfigObject => $ConfigObject, );
my $LogObject = Kernel::System::Log->new( ConfigObject => $ConfigObject, EncodeObject => $EncodeObject, );
my $TimeObject = Kernel::System::Time->new( LogObject => $LogObject, ConfigObject => $ConfigObject, );
my $MainObject = Kernel::System::Main->new( LogObject => $LogObject, EncodeObject => $EncodeObject, ConfigObject => $ConfigObject, );
my $DBObject = Kernel::System::DB->new( ConfigObject => $ConfigObject, EncodeObject => $EncodeObject, MainObject => $MainObject, LogObject => $LogObject, );
my $UserObject = Kernel::System::User->new( ConfigObject => $ConfigObject, LogObject => $LogObject, MainObject => $MainObject, TimeObject => $TimeObject, DBObject => $DBObject, EncodeObject => $EncodeObject, );
my $CustomerUserObject = Kernel::System::CustomerUser->new( ConfigObject => $ConfigObject, LogObject => $LogObject, DBObject => $DBObject, MainObject => $MainObject, EncodeObject => $EncodeObject, UserObject => $UserObject, );
my $TicketObject = Kernel::System::Ticket->new( ConfigObject => $ConfigObject, LogObject => $LogObject, DBObject => $DBObject, MainObject => $MainObject, TimeObject => $TimeObject, EncodeObject => $EncodeObject, CustomerUserObject => $CustomerUserObject, UserObject => $UserObject, );
my $LinkObject = Kernel::System::LinkObject->new( ConfigObject => $ConfigObject, LogObject => $LogObject, DBObject => $DBObject, TimeObject => $TimeObject, MainObject => $MainObject, EncodeObject => $EncodeObject, UserObject => $UserObject, );
print "Enter Customer emails or IDs, separated by a comma.\n"; my $userlist = &promptUser("Customer Emails/IDs");
$userlist =~ s/\s+//g; my @users = split(/,/, $userlist);
my @usergroup; foreach(@users) { my %List = $CustomerUserObject->CustomerSearch( Search => "*$_*" ); if (!%List) { print "Could not find user matching $_\n"; next; } my @Foo = keys %List; my %User = $CustomerUserObject->CustomerUserDataGet( User => $Foo[0], ); print "User: " . $User{'UserFirstname'} ." UID: ". $User{'UserCustomerID'} ."\n"; push @usergroup, \%User; }
my $MasterTicketID = &promptUser("Master Ticket ID");
my $UserID = &promptUser("Agent UserID (numeric)");
# remove spaces # split into an array # foreach over the motherfucker to see if they are valid.
# Create multiple tickets # Send multiple articles
foreach(@usergroup) { print Dumper(\$_); print "User: " . $_->{'UserFirstname'} ." UID: ". $_->{'UserCustomerID'} ."\n"; my $TicketID = $TicketObject->TicketCreate( TN => $TicketObject->TicketCreateNumber(), Queue => 'Raw', Lock => 'unlock', GroupID => 2, Priority => '3 normal', State => 'new', CustomerNo => $_->{'UserCustomerID'}, CustomerUser => $_->{'UserID'}, OwnerID => $UserID, # current owner UserID => $UserID, );
if (!$TicketID) { print "Unable to create Ticket for " . $_->{'UserCustomerID'} ."\n"; next; }
print "Ticket (TicketID:$TicketID) created.\n";
# Add an article here with the From set.
my $ArticleID = $TicketObject->ArticleCreate( TicketID => $TicketID, ArticleType => 'phone', # email-external|email-internal|phone|fax|... SenderType => 'customer', # agent|system|customer From => $_->{'UserFirstname'} . '<' . $_->{'UserID'} .'>', # not required but useful Subject => 'New Slave Ticket', # required Body => 'New Bulk Slave Ticket', # required ContentType => 'text/plain; charset=UTF-8', HistoryType => 'EmailCustomer', # EmailCustomer|Move|AddNote|PriorityUpdate|WebRequestCustomer|... HistoryComment => 'Created by BulkTicket Script', UserID => $UserID, );
if (!$ArticleID) { print "Unable to create Article for " . $_->{'UserCustomerID'} ."\n"; next; }
print "Article (ArticleID:$ArticleID) aded to TicketID $TicketID.\n";
# Set Free Text to Slave. Not sure how to check if it worked.
$TicketObject->TicketFreeTextSet( Counter => 12, # This seems to be TicketFreeText12, so use 12 here Key => "MasterTicket", Value => "Slave", TicketID => $TicketID, # The Slave TicketID UserID => $UserID, );
# Link Ticket to Master as Slave. Even though the documentation on OTRS.org sucks anus, # The ParentChild type is what we want, and we want to set the Direction as Target from the master ticket.
my $True = $LinkObject->LinkAdd( SourceObject => 'Ticket', SourceKey => $MasterTicketID, # Master Ticket ID TargetObject => 'Ticket', TargetKey => $TicketID, # Slave Ticket ID Type => 'ParentChild', Direction => 'Target', State => 'Valid', UserID => $UserID, );
if (!$True) { print "Link to master failed for " . $_->{'UserCustomerID'} ."\n"; next; }
# OK, at this point, we should have a new ticket with an article attached # so a Master Action will send email to all Slaves. }
# Taken without permission from # http://www.devdaily.com/perl/edu/articles/pl010005/pl010005.shtml # on February 2, 2009 # modified to not be annoying about undefined values
sub promptUser {
local($promptString,$defaultValue) = @_;
if (defined($defaultValue)) { print $promptString, "[", $defaultValue, "]: "; } else { print $promptString, ": "; }
$| = 1; # force a flush after our print $_ = <STDIN>; # get the input from STDIN (presumably the keyboard)
chomp;
if (defined($defaultValue) and "$defaultValue") { return $_ ? $_ : $defaultValue; # return $_ if it has a value } else { return $_; } }
exit (0);
=======================================================================
--------------------------------------------------------------------------- Peter Beckman Internet Guy beckman@angryox.com http://www.angryox.com/ --------------------------------------------------------------------------- --------------------------------------------------------------------- OTRS mailing list: otrs - Webpage: http://otrs.org/ Archive: http://lists.otrs.org/pipermail/otrs To unsubscribe: http://lists.otrs.org/cgi-bin/listinfo/otrs
NEW! ENTERPRISE SUBSCRIPTION - Get more information NOW! http://www.otrs.com/en/support/enterprise-subscription/
participants (2)
-
Michiel Beijen
-
Peter Beckman