Hi list, This email doesn't ask a question. Instead, I'll describe the solution to a problem, just in case anyone else finds it useful.
=Problem= How do you use an event module to compute and store a value in a dynamic field, with the purpose of showing it in customer UI, in the grid where the list of tickets is shown? A real world example would be: How do you show a new column holding the moment when the latest article visible to the customer was added to the ticket? =Solution= The aforementioned grid is shown in a location identified in OTRS lingo as the CustomerTicketOverview view. This grid supports some customization via SysConfig: you can show two additional columns, Owner and Queue, and you can also show an arbitrary number of ticket dynamic fields. Thus we'll need to make use of a ticket dynamic field for our new column, since we want to avoid changing OTRS's original source files to keep future upgrades as smooth as possible. Now all we need is a way to compute the data for the new column, which I'll start referring to as "Last Updated". The solution is to write an Event Module, which is an extensibility mechanism provided by OTRS, so it's likely that it will function even across future OTRS versions even though it was tested on OTRS 3.2.3. The event module is a Perl source file, that we'll need to write, containing a class that is executed by OTRS whenever events that we'll specify are triggered. OTRS will provide our code with information related to the event context and so we'll have everything required to compute data for "Last Updated". Our event module will look at each article as it's added and determine if it'll be visible to the customer. If so, it will update the corresponding ticket's dynamic field for "Last Updated" to match the creation date of this article. ==Steps Towards Solution== 1. Create, via admin UI, a ticket dynamic field of type DateTime. I'll assume its name is DtTmLastChangeForCustUI but you can use anything else. 2. Configure, via SysConfig, the CustomerTicketOverview view to show DtTmLastChangeForCustUI, by adding its name to Ticket::Frontend::CustomerTicketOverview###DynamicField. 3. Create an event module to compute the values for DtTmLastChangeForCustUI. Because I have no idea how to add attachments that will also be available in the mailing list archives, I'll provide the code for this event module embedded in this email. You'll need to copy and paste the code in a source file named OtrsInstallDir\Custom\Kernel\System\Ticket\Event\LastChangeForCustomerUI.pm. The path for this source file is important. The provided code contains at least one small bug: it uses the date when the article was last changed instead of the date when it was created. Due to the code being designed to work only on ArticleCreate, there are no bad effects from this bug. 4. Hook up the event module to OTRS. You'll need to copy and paste the code for LastChangeForCustomerUI.xml from this email to OtrsInstallDir\Config\Files\LastChangeForCustomerUI.xml. Again, the path for this file is important. 5. At this point you'll want to logoff from OTRS using an admin account and logon again. Then navigate to SysConfig and there you should find a new group in the dropdown on the left, named LastChangeForCustomerUI. 6. Set the content of the TargetedDynamicFieldName key to DtTmLastChangeForCustUI for the new setting Ticket::EventModulePost###LastChangeForCustomerUI. 7. At this point you should be all set for the functionality to work but keep in mind that the field will be empty for already existent tickets so it will start having meaningful values as tickets are created or articles are added to older tickets. My company (www.totalsoft.ro) was behind the development of this small customization and they've decided it's OK to publish it to the public domain. So there are no licensing issues tied to this code. Enjoy, Bogdan Iosif Code for LastChangeForCustomerUI.xml: <?xml version="1.0" encoding="utf-8" ?> <otrs_config version="1.0" init="Changes"> <ConfigItem Name="Ticket::EventModulePost###LastChangeForCustomerUI" Required="0" Valid="1"> <Description Lang="en">Stores in TargetedDynamicFieldName the moment of the last ticket change, as it should be reported in the customer interface. The moment is captured when an article visible in the customer interface is created. This is why Event must be ArticleCreate. TargetedDynamicFieldName must be the name of an existent ticket dynamic field of "Date / Time" type.</Description> <Group>LastChangeForCustomerUI</Group> <SubGroup>LastChangeForCustomerUI</SubGroup> <Setting> <Hash> <Item Key="Module">Kernel::System::Ticket::Event::LastChangeForCustomerUI</Item> <Item Key="Event">(ArticleCreate)</Item> <Item Key="TargetedDynamicFieldName"></Item> </Hash> </Setting> </ConfigItem> </otrs_config> Code for LastChangeForCustomerUI.pm: # -- # Kernel/System/Ticket/Event/LastChangeForCustomerUI.pm # - Sets a configurable dynamic field to the changed date of the latest article visible to the customer # -- package Kernel::System::Ticket::Event::LastChangeForCustomerUI; use strict; use warnings; use Kernel::System::DynamicField; use Kernel::System::DynamicField::Backend; use Kernel::System::VariableCheck qw(:all); sub new { my ( $Type, %Param ) = @_; # allocate new hash for object my $Self = {}; bless( $Self, $Type ); # get needed objects for (qw(ConfigObject TicketObject LogObject TimeObject UserObject CustomerUserObject SendmailObject)) { $Self->{$_} = $Param{$_} || die "Got no $_!"; } # create additional objects $Self->{DynamicFieldObject} = Kernel::System::DynamicField->new( EncodeObject => $Param{TicketObject}->{EncodeObject}, MainObject => $Param{TicketObject}->{MainObject}, DBObject => $Param{TicketObject}->{DBObject}, %Param, ); $Self->{BackendObject} = Kernel::System::DynamicField::Backend->new( EncodeObject => $Param{TicketObject}->{EncodeObject}, MainObject => $Param{TicketObject}->{MainObject}, DBObject => $Param{TicketObject}->{DBObject}, TimeObject => $Param{TicketObject}->{TimeObject}, %Param, ); return $Self; } sub Run { my ( $Self, %Param ) = @_; =Enable only during debug $Self->{LogObject}->Log( Priority => 'debug', Message => 'Run() Dumping %Param:' ); $Self->{LogObject}->Dumper( Data => %Param ); =cut # check needed stuff for (qw(Data Event Config UserID)) { if ( !$Param{$_} ) { $Self->{LogObject}->Log( Priority => 'error', Message => "Need $_!" ); return; } } if ( $Param{Event} ne 'ArticleCreate' ) { $Self->{LogObject}->Log( Priority => 'error', Message => "Invalid event module configuration. Invoked on '$Param{Event}' while designed only for 'ArticleCreate'." ); return; } if ( !$Param{Config}->{TargetedDynamicFieldName} ) { $Self->{LogObject}->Log( Priority => 'error', Message => "Invalid event module configuration. Unspecified 'TargetedDynamicFieldName'." ); return; } for (qw(TicketID ArticleID)) { if ( !$Param{Data}->{$_} ) { $Self->{LogObject}->Log( Priority => 'error', Message => "Need $_ in Data!" ); return; } } # get dynamic field config my $DynamicFieldConfig = $Self->{DynamicFieldObject}->DynamicFieldGet( Name => $Param{Config}->{TargetedDynamicFieldName} ); if ( $DynamicFieldConfig->{FieldType} ne 'DateTime' ) { $Self->{LogObject}->Log( Priority => 'error', Message => "Invalid event module configuration. '$Param{Config}->{TargetedDynamicFieldName}' dynamic field type is not 'DateTime'." ); return; } my @CustomerArticleTypes = $Self->{TicketObject}->ArticleTypeList( Type => 'Customer' ); my %Article = $Self->{TicketObject}->ArticleGet( ArticleID => $Param{Data}->{ArticleID}, ArticleType => \@CustomerArticleTypes, ); if(!%Article) { =Enable only during debug $Self->{LogObject}->Log( Priority => 'debug', Message => "Skipping LastChangeForCustomerUI update because article id $Param{Data}->{ArticleID} was not found amongst 'Customer' articles for ticket id $Param{Data}->{TicketID}." ); =cut return; } # set the value my $Success = $Self->{BackendObject}->ValueSet( DynamicFieldConfig => $DynamicFieldConfig, ObjectID => $Param{Data}->{TicketID}, Value => $Article{Changed}, UserID => $Param{UserID}, ); if ( !$Success ) { $Self->{LogObject}->Log( Priority => 'error', Message => "Can not set value to current time for dynamic field $DynamicFieldConfig->{Name}!" ); } return 1; } 1;
--------------------------------------------------------------------- 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