
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/ ---------------------------------------------------------------------------