Adding customer name in Customer ticket overview

Moderator: crythias

Post Reply
JHS
Znuny newbie
Posts: 25
Joined: 13 Oct 2016, 11:22
Znuny Version: 6 PL 4

Adding customer name in Customer ticket overview

Post by JHS »

Hello everybody

I'm using OTRS 5.0.13 on CentOS 7

I was wondering if it is possible to add the customer user name of the user that logged the ticket in an extra column in the customer ticket overview.
otrs_customer_ticket_overview.png
A customer has multiple employees that can create tickets and their supervisor would like to see a list of the tickets with the addition of the name of the original ticket reporter.

I've found the option Frontend::Customer::TicketOverview, but apparently this does not provide the same options as I was expecting like in Frontend::Agent::DefaultOverviewColumns.
I can add dynamicfield, but since the CustomerName (full name of the customer user actually) is not a dynamicfield, I can't enable this.

Is there another way to add this or am I overlooking something?
You do not have the required permissions to view the files attached to this post.
OTRS 6.0.5
RStraub
Znuny guru
Posts: 2210
Joined: 13 Mar 2014, 09:16
Znuny Version: 6.0.14
Real Name: Rolf Straub

Re: Adding customer name in Customer ticket overview

Post by RStraub »

No, it seem you'd need a modification of the OTRS framework to acomplish that.
Currently using: OTRS 6.0.14 -- MariaDB -- Ubuntu 16 LTS
JHS
Znuny newbie
Posts: 25
Joined: 13 Oct 2016, 11:22
Znuny Version: 6 PL 4

Re: Adding customer name in Customer ticket overview

Post by JHS »

RStraub wrote:No, it seem you'd need a modification of the OTRS framework to acomplish that.
Thank you very much for your quick reply.
At this moment I don't have a lot of experience manually modifying the OTRS framework, can you guide me in the right direction?
Or perhaps link me some more information so I know where to look? Thanks!
OTRS 6.0.5
RStraub
Znuny guru
Posts: 2210
Joined: 13 Mar 2014, 09:16
Znuny Version: 6.0.14
Real Name: Rolf Straub

Re: Adding customer name in Customer ticket overview

Post by RStraub »

Hi there,

that's actually not too hard.

1) Create a new folder (if it's not there yet) ~otrs/Custom/
2) Copy these files to the new folder (PRESERVING the same folder structure):
Kernel/Output/HTML/Templates/Standard/CustomerTicketOverview.tt
Kernel/Modules/CustomerTicketOverview.pm
so as otrs-user:
cp -p ~/Kernel/Output/HTML/Templates/Standard/CustomerTicketOverview.tt ~/Custom/Kernel/Output/HTML/Templates/Standard/CustomerTicketOverview.tt

3) Modify the template file (.tt):
3.1.) Add a new html header:
https://github.com/OTRS/otrs/blob/rel-5 ... iew.tt#L39
e.g.:

Code: Select all

                    <th class="State [% Data.CreatedBy| uri %]">
                        <a href="[% Env("Baselink") %]Action=[% Env("Action") %];Subaction=[% Env("Subaction") %];SortBy=CreatedBy;OrderBy=[% Data.OrderBy | uri %];Filter=[% Data.Filter | uri %]">
                            [% Translate("CreatedBy") | html %]
                        </a>
                    </th>
3.2.) Add a new data row:
https://github.com/OTRS/otrs/blob/rel-5 ... ew.tt#L110
e.g.:

Code: Select all

<td class="Status">[% Translate(Data.CreatedBy) | html %]</td>
4) Add the created-by name to the data hash in the perl module here:
https://github.com/OTRS/otrs/blob/rel-5 ... ew.pm#L677
Add these lines:

Code: Select all

        $Param{CreatedBy} = $Kernel::OM->Get('Kernel::System::CustomerUser')->CustomerName(
            UserLogin => $Ticket{CreateBy},
        );
This should suffice to give you the additional column.
Currently using: OTRS 6.0.14 -- MariaDB -- Ubuntu 16 LTS
JHS
Znuny newbie
Posts: 25
Joined: 13 Oct 2016, 11:22
Znuny Version: 6 PL 4

Re: Adding customer name in Customer ticket overview

Post by JHS »

Thank you for your response!
How does one go about to enable these custom files?

Is it just enough to have them in the correct directory .../otrs/Custom/Kernel/...? Or do I need to change some option in sysconfig?
I'm sorry for this question, but I've never used custom pages for OTRS.

Thanks in advance!
OTRS 6.0.5
RStraub
Znuny guru
Posts: 2210
Joined: 13 Mar 2014, 09:16
Znuny Version: 6.0.14
Real Name: Rolf Straub

Re: Adding customer name in Customer ticket overview

Post by RStraub »

No, putting them into the ~/Custom/ folder is enough.

OTRS scans first all files in ~/... and THEN overwrites the files with those found in ~/Custom/..

This is true for most of the perl files and the template files. There are some exceptions, like the Config.pm or the config files in ~/Kernel/Config/Files.

It's only important to have the exact same folder structure under ~/Custom as you have in the original path. Also make sure to migrate the Custom folder on upgrades ;)
Currently using: OTRS 6.0.14 -- MariaDB -- Ubuntu 16 LTS
JHS
Znuny newbie
Posts: 25
Joined: 13 Oct 2016, 11:22
Znuny Version: 6 PL 4

Re: Adding customer name in Customer ticket overview

Post by JHS »

Hello

I've added the additions that you replied in the /opt/otrs/Custom directory. After restarting apache, I don't see any changes. Did I do something wrong? These are my custom files:

CustomerTicketOverview.tt

Code: Select all

# --
# Copyright (C) 2001-2016 xxx, http://otrs.com/
# --
# This software comes with ABSOLUTELY NO WARRANTY. For details, see
# the enclosed file COPYING for license information (AGPL). If you
# did not receive this file, see http://www.gnu.org/licenses/agpl.txt.
# --
<div id="MainBox" class="TicketView ARIARoleMain [% Config("Ticket::Frontend::CustomerTicketOverviewSortable") %]">
[% RenderBlockStart("Filled") %]
    <div class="ActionRow">
        <ul class="Filter Tabs">
[% RenderBlockStart("FilterHeader") %]
            <li>
                <a class="[% Data.ClassA | html %]" href="[% Env("Baselink") %]Action=[% Env("Action") %];Subaction=[% Env("Subaction") %];Filter=[% Data.Filter | uri %];SortBy=[% Data.SortBy | uri %];OrderBy=[% Data.OrderBy | uri %];">
                    [% Translate(Data.Name) | html %] ([% Data.Count | html %])
                </a>
            </li>
[% RenderBlockEnd("FilterHeader") %]
        </ul>
        <div class="Tabs Pagination">
            [% Data.SiteNavBar %]
        </div>
        <div class="Clear"></div>
    </div>
    <div class="Content">
        <table class="Overview">
            <thead>
                <tr>
                    <th class="Ticket [% Data.TicketSort | uri %]">
                        <a href="[% Env("Baselink") %]Action=[% Env("Action") %];Subaction=[% Env("Subaction") %];SortBy=Ticket;OrderBy=[% Data.OrderBy | uri %];Filter=[% Data.Filter | uri %]">
                            [% Config("Ticket::Hook") %]
                        </a>
                    </th>
                    <th class="Title [% Data.TitleSort | uri %]">
                        <a href="[% Env("Baselink") %]Action=[% Env("Action") %];Subaction=[% Env("Subaction") %];SortBy=Title;OrderBy=[% Data.OrderBy | uri %];Filter=[% Data.Filter | uri %]">
                            [% Translate("Title") | html %]
                        </a>
                    </th>
                    <th class="State [% Data.StateSort | uri %]">
                        <a href="[% Env("Baselink") %]Action=[% Env("Action") %];Subaction=[% Env("Subaction") %];SortBy=State;OrderBy=[% Data.OrderBy | uri %];Filter=[% Data.Filter | uri %]">
                            [% Translate("State") | html %]
                        </a>
                    </th>
		    <th class="State [% Data.CreatedBy| uri %]">
                        <a href="[% Env("Baselink") %]Action=[% Env("Action") %];Subaction=[% Env("Subaction") %];SortBy=CreatedBy;OrderBy=[% Data.OrderBy | uri %];Filter=[% Data.Filter | uri %]">
                            [% Translate("CreatedBy") | html %]
                        </a>
                    </th>
[% RenderBlockStart("OverviewNavBarPageOwner") %]
                    <th class="Owner [% Data.OwnerSort | uri %]">
                        <a href="[% Env("Baselink") %]Action=[% Env("Action") %];Subaction=[% Env("Subaction") %];SortBy=Owner;OrderBy=[% Data.OrderBy | uri %];Filter=[% Data.Filter | uri %]">
                            [% Translate("Owner") | html %]
                        </a>
                    </th>
[% RenderBlockEnd("OverviewNavBarPageOwner") %]
[% RenderBlockStart("OverviewNavBarPageQueue") %]
                    <th class="Queue [% Data.QueueSort | uri %]">
                        <a href="[% Env("Baselink") %]Action=[% Env("Action") %];Subaction=[% Env("Subaction") %];SortBy=Queue;OrderBy=[% Data.OrderBy | uri %];Filter=[% Data.Filter | uri %]">
                            [% Translate("Queue") | html %]
                        </a>
                    </th>
[% RenderBlockEnd("OverviewNavBarPageQueue") %]
[% RenderBlockStart("OverviewNavBarPageDynamicField") %]
                    <th class="DynamicField Last [% Data.CSS | html %]">
[% RenderBlockStart("OverviewNavBarPageDynamicFieldSortable") %]
                        <a name="OverviewControl" href="[% Env("Baselink") %]Action=[% Env("Action") %];Subaction=[% Env("Subaction") %];SortBy=DynamicField_[% Data.DynamicFieldName | uri %];OrderBy=[% Data.OrderBy | uri %];Filter=[% Data.Filter | uri %]">[% Translate(Data.Label) | html %]</a>
[% RenderBlockEnd("OverviewNavBarPageDynamicFieldSortable") %]
[% RenderBlockStart("OverviewNavBarPageDynamicFieldNotSortable") %]
                        <span>[% Translate(Data.Label) | html %]</span>
[% RenderBlockEnd("OverviewNavBarPageDynamicFieldNotSortable") %]
                    </th>
[% RenderBlockEnd("OverviewNavBarPageDynamicField") %]
# example of how to use fixed dynamic field blocks for customizations
# Note: Field1 and Field2 are the names of the fields and had to be replaced with the actual
# field names
#[% RenderBlockStart("OverviewNavBarPageDynamicField_Field1") %]
#                    <th class="DynamicField Last [% Data.CSS | html %]">
#[% RenderBlockStart("OverviewNavBarPageDynamicField_Field1_Sortable") %]
#                        <a name="OverviewControl" href="[% Env("Baselink") %]Action=[% Env("Action") %];Subaction=[% Env("Subaction") %];SortBy=DynamicField_[% Data.DynamicFieldName | uri %];OrderBy=[% Data.OrderBy | uri %];Filter=[% Data.Filter | uri %]">[% Translate(Data.Label) | html %]</a>
#[% RenderBlockEnd("OverviewNavBarPageDynamicField_Field1_Sortable") %]
#[% RenderBlockStart("OverviewNavBarPageDynamicField_Field1_NotSortable") %]
#                        <span>[% Translate(Data.Label) | html %]</span>
#[% RenderBlockEnd("OverviewNavBarPageDynamicField_Field1_NotSortable") %]
#                    </th>
#[% RenderBlockEnd("OverviewNavBarPageDynamicField_Field1") %]
#[% RenderBlockStart("OverviewNavBarPageDynamicField_Field2") %]
#                    <th class="DynamicField Last [% Data.CSS | html %]">
#[% RenderBlockStart("OverviewNavBarPageDynamicField_Field2_Sortable") %]
#                        <a name="OverviewControl" href="[% Env("Baselink") %]Action=[% Env("Action") %];[% Data.LinkSort %];SortBy=DynamicField_[% Data.DynamicFieldName | uri %];OrderBy=[% Data.OrderBy | uri %]">[% Translate(Data.Label) | html %]</a>
#[% RenderBlockEnd("OverviewNavBarPageDynamicField_Field2_Sortable") %]
#[% RenderBlockStart("OverviewNavBarPageDynamicField_Field2_NotSortable") %]
#                        <span>[% Translate(Data.Label) | html %]</span>
#[% RenderBlockEnd("OverviewNavBarPageDynamicField_Field2_NotSortable") %]
#                    </th>
#[% RenderBlockEnd("OverviewNavBarPageDynamicField_Field2") %]
                    <th class="Age [% Data.AgeSort | uri %]">
                        <a href="[% Env("Baselink") %]Action=[% Env("Action") %];Subaction=[% Env("Subaction") %];SortBy=Age;OrderBy=[% Data.OrderBy | uri %];Filter=[% Data.Filter | uri %]">
                            [% Translate("Age") | html %]
                        </a>
                    </th>
                </tr>
            </thead>
            <tbody>
[% RenderBlockStart("Record") %]
                <tr class="MasterAction">
                    <td class="Ticket">
                        <a href="[% Env("Baselink") %]Action=CustomerTicketZoom;TicketNumber=[% Data.TicketNumber | uri %]" class="MasterActionLink">[% Data.TicketNumber | html %]</a>
                    </td>
                    <td class="Title">
                        <div>
                            <h2>[% Data.Subject | truncate(60) | html %]</h2>
                            &nbsp;-&nbsp; [% Data.Body | truncate(200) | html %]
                        </div>
                    </td>
                    <td class="Status">[% Translate(Data.State) | html %]</td>
					<td class="Status">[% Translate(Data.CreatedBy) | html %]</td>
[% RenderBlockStart("RecordOwner") %]
                    <td class="Owner">[% Data.OwnerName | html %]</td>
[% RenderBlockEnd("RecordOwner") %]
[% RenderBlockStart("RecordQueue") %]
                    <td class="Queue" title="[% Data.Queue | html %]">[% Data.Queue | truncate(20) | html %]</td>
[% RenderBlockEnd("RecordQueue") %]
[% RenderBlockStart("RecordDynamicField") %]
                    <td>
                        <div title="[% Data.Title | html %]">
[% RenderBlockStart("RecordDynamicFieldLink") %]
                            <a href="[% Data.Link | Interpolate %]" class="DynamicFieldLink">[% Data.Value %]</a>
[% RenderBlockEnd("RecordDynamicFieldLink") %]
[% RenderBlockStart("RecordDynamicFieldPlain") %]
                            [% Data.Value %]
[% RenderBlockEnd("RecordDynamicFieldPlain") %]
                        </div>
                    </td>
[% RenderBlockEnd("RecordDynamicField") %]
# example of how to use fixed dynamic field blocks for customizations
# Note: Field1 and Field2 are the names of the fields and had to be replaced with the actual
# field names
#[% RenderBlockStart("RecordDynamicField_Field1") %]
#                    <td>
#                        <div title="[% Data.Title | html %]">
#[% RenderBlockStart("RecordDynamicField1Link") %]
#                            <a href="[% Data.Link | Interpolate %]" class="DynamicFieldLink">[% Data.Value %]</a>
#[% RenderBlockEnd("RecordDynamicField1Link") %]
#[% RenderBlockStart("RecordDynamicField1Plain") %]
#                            [% Data.Value %]
#[% RenderBlockEnd("RecordDynamicField1Plain") %]
#                        </div>
#                    </td>
#[% RenderBlockEnd("RecordDynamicField_Field1") %]
#[% RenderBlockStart("RecordDynamicField_Field2") %]
#                    <td>
#                        <div title="[% Data.Title | html %]">
#[% RenderBlockEnd("RecordDynamicField1Link") %]
#                            <a href="[% Data.Link | Interpolate %]" class="DynamicFieldLink">[% Data.Value %]</a>
#[% RenderBlockEnd("RecordDynamicField1Link") %]
#[% RenderBlockEnd("RecordDynamicField1Plain") %]
#                            [% Data.Value %]
#[% RenderBlockEnd("RecordDynamicField1Plain") %]
#                        </div>
#                    </td>
#[% RenderBlockEnd("RecordDynamicField_Field2") %]
                    <td class="Age" title="[% Data.Created | Localize("TimeShort") | html %]">[% Data.CustomerAge | truncate(20) | html %]</td>
                </tr>
[% RenderBlockEnd("Record") %]
[% WRAPPER JSOnDocumentComplete %]
<script type="text/javascript">//<![CDATA[
    $('.MasterAction').bind('click', function (Event) {
        var $MasterActionLink = $(this).find('.MasterActionLink');
        // only act if the link was not clicked directly
        if (Event.target !== $MasterActionLink.get(0)) {
            window.location = $MasterActionLink.attr('href');
            return false;
        }
    });
//]]></script>
[% END %]
            </tbody>
        </table>
    </div>
[% RenderBlockStart("FilterFooter") %]
    <div id="BottomActionRow" class="ActionRow BigButtons">
        <ul class="Tabs Filter">
[% RenderBlockStart("FilterFooterItem") %]
            <li class="[% Data.ClassLI | html %]">
                <a class="[% Data.ClassA | html %]" href="[% Env("Baselink") %]Action=[% Env("Action") %];Subaction=[% Env("Subaction") %];Filter=[% Data.Filter | uri %];SortBy=[% Data.SortBy | uri %];OrderBy=[% Data.OrderBy | uri %];">
                    [% Translate(Data.Name) | html %] ([% Data.Count | html %])
                </a>
            </li>
[% RenderBlockEnd("FilterFooterItem") %]
            <li class="Clear"></li>
        </ul>
        <div class="Tabs Pagination">
            [% Data.SiteNavBar %]
        </div>
        <div class="Clear"></div>
    </div>
[% RenderBlockEnd("FilterFooter") %]
[% RenderBlockEnd("Filled") %]

[% RenderBlockStart("Empty") %]
    <div class="Placeholder">
[% RenderBlockStart("EmptyDefault") %]
        <h2>[% Translate("Welcome!") | html %]</h2>
        <p>
            [% Translate("Please click the button below to create your first ticket.") | html %]
        </p>
[% RenderBlockStart("EmptyDefaultButton") %]
        <a class="Button" href="[% Env("Baselink") %]Action=CustomerTicketMessage">[% Translate("Create your first ticket") | html %]</a>
[% RenderBlockEnd("EmptyDefaultButton") %]
[% RenderBlockEnd("EmptyDefault") %]
[% RenderBlockStart("EmptyCustom") %]
        <h2>[% Translate(Data.Title) | html %]</h2>
        <p>
            [% Translate(Data.Text) | html %]
        </p>
[% RenderBlockStart("EmptyCustomButton") %]
        <a class="Button" href="[% Env("Baselink") %]Action=CustomerTicketMessage">[% Translate(Data.Button) | html %]</a>
[% RenderBlockEnd("EmptyCustomButton") %]
[% RenderBlockEnd("EmptyCustom") %]
    </div>
[% RenderBlockEnd("Empty") %]
</div>
CustomerTicketOverview.pm

Code: Select all

# --
# Copyright (C) 2001-2016 xxx, http://otrs.com/
# --
# This software comes with ABSOLUTELY NO WARRANTY. For details, see
# the enclosed file COPYING for license information (AGPL). If you
# did not receive this file, see http://www.gnu.org/licenses/agpl.txt.
# --

package Kernel::Modules::CustomerTicketOverview;
## nofilter(TidyAll::Plugin::OTRS::Perl::DBObject)

use strict;
use warnings;

our $ObjectManagerDisabled = 1;

use Kernel::System::VariableCheck qw(:all);
use Kernel::Language qw(Translatable);

sub new {
    my ( $Type, %Param ) = @_;

    # allocate new hash for object
    my $Self = {%Param};
    bless( $Self, $Type );

    return $Self;
}

sub Run {
    my ( $Self, %Param ) = @_;

    my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
    my $ConfigObject = $Kernel::OM->Get('Kernel::Config');
    my $ParamObject  = $Kernel::OM->Get('Kernel::System::Web::Request');

    # disable output of customer company tickets
    my $DisableCompanyTickets = $ConfigObject->Get('Ticket::Frontend::CustomerDisableCompanyTicketAccess');

    # check subaction
    if ( !$Self->{Subaction} ) {
        return $LayoutObject->Redirect(
            OP => 'Action=CustomerTicketOverview;Subaction=MyTickets',
        );
    }
    elsif ( $Self->{Subaction} eq 'CompanyTickets' && $DisableCompanyTickets ) {
        return $LayoutObject->CustomerNoPermission( WithHeader => 'yes' );
    }

    # check needed CustomerID
    if ( !$Self->{UserCustomerID} ) {
        my $Output = $LayoutObject->CustomerHeader(
            Title => Translatable('Error'),
        );
        $Output .= $LayoutObject->CustomerError(
            Message => Translatable('Need CustomerID!'),
        );
        $Output .= $LayoutObject->CustomerFooter();
        return $Output;
    }

    $Kernel::OM->Get('Kernel::System::AuthSession')->UpdateSessionID(
        SessionID => $Self->{SessionID},
        Key       => 'LastScreenOverview',
        Value     => $Self->{RequestedURL},
    );

    my $SortBy         = $ParamObject->GetParam( Param => 'SortBy' )  || 'Age';
    my $OrderByCurrent = $ParamObject->GetParam( Param => 'OrderBy' ) || 'Down';

    # filter definition
    my %Filters = (
        MyTickets => {
            All => {
                Name   => 'All',
                Prio   => 1000,
                Search => {
                    CustomerUserLoginRaw => $Self->{UserID},
                    OrderBy              => $OrderByCurrent,
                    SortBy               => $SortBy,
                    CustomerUserID       => $Self->{UserID},
                    Permission           => 'ro',
                },
            },
            Open => {
                Name   => 'Open',
                Prio   => 1100,
                Search => {
                    CustomerUserLoginRaw => $Self->{UserID},
                    StateType            => 'Open',
                    OrderBy              => $OrderByCurrent,
                    SortBy               => $SortBy,
                    CustomerUserID       => $Self->{UserID},
                    Permission           => 'ro',
                },
            },
            Closed => {
                Name   => 'Closed',
                Prio   => 1200,
                Search => {
                    CustomerUserLoginRaw => $Self->{UserID},
                    StateType            => 'Closed',
                    OrderBy              => $OrderByCurrent,
                    SortBy               => $SortBy,
                    CustomerUserID       => $Self->{UserID},
                    Permission           => 'ro',
                },
            },
        },
    );

    my $UserObject = $Kernel::OM->Get('Kernel::System::CustomerUser');

    # add filter for customer company if not disabled
    if ( !$DisableCompanyTickets ) {
        $Filters{CompanyTickets} = {
            All => {
                Name   => 'All',
                Prio   => 1000,
                Search => {
                    CustomerIDRaw =>
                        [ $UserObject->CustomerIDs( User => $Self->{UserLogin} ) ],
                    OrderBy        => $OrderByCurrent,
                    SortBy         => $SortBy,
                    CustomerUserID => $Self->{UserID},
                    Permission     => 'ro',
                },
            },
            Open => {
                Name   => 'Open',
                Prio   => 1100,
                Search => {
                    CustomerIDRaw =>
                        [ $UserObject->CustomerIDs( User => $Self->{UserLogin} ) ],
                    StateType      => 'Open',
                    OrderBy        => $OrderByCurrent,
                    SortBy         => $SortBy,
                    CustomerUserID => $Self->{UserID},
                    Permission     => 'ro',
                },
            },
            Closed => {
                Name   => 'Closed',
                Prio   => 1200,
                Search => {
                    CustomerIDRaw =>
                        [ $UserObject->CustomerIDs( User => $Self->{UserLogin} ) ],
                    StateType      => 'Closed',
                    OrderBy        => $OrderByCurrent,
                    SortBy         => $SortBy,
                    CustomerUserID => $Self->{UserID},
                    Permission     => 'ro',
                },
            },
        };
    }

    my $FilterCurrent = $ParamObject->GetParam( Param => 'Filter' ) || 'Open';

    # check if filter is valid
    if ( !$Filters{ $Self->{Subaction} }->{$FilterCurrent} ) {
        my $Output = $LayoutObject->CustomerHeader(
            Title => Translatable('Error'),
        );
        $Output .= $LayoutObject->CustomerError(
            Message => $LayoutObject->{LanguageObject}->Translate( 'Invalid Filter: %s!', $FilterCurrent ),
        );
        $Output .= $LayoutObject->CustomerFooter();
        return $Output;
    }

    # check if archive search is allowed, otherwise search for all tickets
    my %SearchInArchive;
    if (
        $ConfigObject->Get('Ticket::ArchiveSystem')
        && !$ConfigObject->Get('Ticket::CustomerArchiveSystem')
        )
    {
        $SearchInArchive{ArchiveFlags} = [ 'y', 'n' ];
    }

    my %NavBarFilter;
    my $Counter         = 0;
    my $AllTickets      = 0;
    my $AllTicketsTotal = 0;
    my $TicketObject    = $Kernel::OM->Get('Kernel::System::Ticket');

    for my $Filter ( sort keys %{ $Filters{ $Self->{Subaction} } } ) {
        $Counter++;

        my $Count = $TicketObject->TicketSearch(
            %{ $Filters{ $Self->{Subaction} }->{$Filter}->{Search} },
            %SearchInArchive,
            Result => 'COUNT',
        );

        my $ClassA = '';
        if ( $Filter eq $FilterCurrent ) {
            $ClassA     = 'Selected';
            $AllTickets = $Count;
        }
        if ( $Filter eq 'All' ) {
            $AllTicketsTotal = $Count;
        }
        $NavBarFilter{ $Filters{ $Self->{Subaction} }->{$Filter}->{Prio} } = {
            %{ $Filters{ $Self->{Subaction} }->{$Filter} },
            Count  => $Count,
            Filter => $Filter,
            ClassA => $ClassA,
        };
    }

    my $StartHit = int( $ParamObject->GetParam( Param => 'StartHit' ) || 1 );
    my $PageShown = $Self->{UserShowTickets} || 1;

    if ( !$AllTicketsTotal ) {
        $LayoutObject->Block(
            Name => 'Empty',
        );

        my $CustomTexts = $ConfigObject->Get('Ticket::Frontend::CustomerTicketOverviewCustomEmptyText');

        if ( ref $CustomTexts eq 'HASH' ) {
            $LayoutObject->Block(
                Name => 'EmptyCustom',
                Data => $CustomTexts,
            );

            # only show button, if frontend module for NewTicket is registered
            # and button text is configured
            if (
                ref $ConfigObject->Get('CustomerFrontend::Module')->{CustomerTicketMessage}
                eq 'HASH'
                && defined $ConfigObject->Get('Ticket::Frontend::CustomerTicketOverviewCustomEmptyText')
                ->{Button}
                )
            {
                $LayoutObject->Block(
                    Name => 'EmptyCustomButton',
                    Data => $CustomTexts,
                );
            }
        }
        else {
            $LayoutObject->Block(
                Name => 'EmptyDefault',
            );

            # only show button, if frontend module for NewTicket is registered
            if (
                ref $ConfigObject->Get('CustomerFrontend::Module')->{CustomerTicketMessage}
                eq 'HASH'
                )
            {
                $LayoutObject->Block(
                    Name => 'EmptyDefaultButton',
                );
            }
        }
    }
    else {

        # create & return output
        my $Link = 'SortBy=' . $LayoutObject->Ascii2Html( Text => $SortBy )
            . ';OrderBy=' . $LayoutObject->Ascii2Html( Text => $OrderByCurrent )
            . ';Filter=' . $LayoutObject->Ascii2Html( Text => $FilterCurrent )
            . ';Subaction=' . $LayoutObject->Ascii2Html( Text => $Self->{Subaction} )
            . ';';
        my %PageNav = $LayoutObject->PageNavBar(
            Limit     => 10000,
            StartHit  => $StartHit,
            PageShown => $PageShown,
            AllHits   => $AllTickets,
            Action    => 'Action=CustomerTicketOverview',
            Link      => $Link,
            IDPrefix  => 'CustomerTicketOverview',
        );

        my $OrderBy = 'Down';
        if ( $OrderByCurrent eq 'Down' ) {
            $OrderBy = 'Up';
        }
        my $Sort       = '';
        my $StateSort  = '';
        my $TicketSort = '';
        my $TitleSort  = '';
        my $AgeSort    = '';
        my $QueueSort  = '';
        my $OwnerSort  = '';

        # this sets the opposite to the $OrderBy
        if ( $OrderBy eq 'Down' ) {
            $Sort = 'SortAscending';
        }
        if ( $OrderBy eq 'Up' ) {
            $Sort = 'SortDescending';
        }

        if ( $SortBy eq 'State' ) {
            $StateSort = $Sort;
        }
        elsif ( $SortBy eq 'Ticket' ) {
            $TicketSort = $Sort;
        }
        elsif ( $SortBy eq 'Title' ) {
            $TitleSort = $Sort;
        }
        elsif ( $SortBy eq 'Age' ) {
            $AgeSort = $Sort;
        }
        elsif ( $SortBy eq 'Queue' ) {
            $QueueSort = $Sort;
        }
        elsif ( $SortBy eq 'Owner' ) {
            $OwnerSort = $Sort;
        }
        $LayoutObject->Block(
            Name => 'Filled',
            Data => {
                %Param,
                %PageNav,
                OrderBy    => $OrderBy,
                StateSort  => $StateSort,
                TicketSort => $TicketSort,
                TitleSort  => $TitleSort,
                AgeSort    => $AgeSort,
                Filter     => $FilterCurrent,
            },
        );

        my $Owner = $ConfigObject->Get('Ticket::Frontend::CustomerTicketOverview')->{Owner};
        my $Queue = $ConfigObject->Get('Ticket::Frontend::CustomerTicketOverview')->{Queue};

        if ($Owner) {
            $LayoutObject->Block(
                Name => 'OverviewNavBarPageOwner',
                Data => {
                    OrderBy   => $OrderBy,
                    OwnerSort => $OwnerSort,
                    Filter    => $FilterCurrent,
                },
            );
        }

        if ($Queue) {
            $LayoutObject->Block(
                Name => 'OverviewNavBarPageQueue',
                Data => {
                    OrderBy   => $OrderBy,
                    QueueSort => $QueueSort,
                    Filter    => $FilterCurrent,
                },
            );
        }

        # show header filter
        for my $Key ( sort keys %NavBarFilter ) {
            $LayoutObject->Block(
                Name => 'FilterHeader',
                Data => {
                    %{ $NavBarFilter{$Key} },
                },
            );
        }

        # show footer filter - show only if more the one page is available
        if ( $AllTickets > $PageShown ) {
            $LayoutObject->Block(
                Name => 'FilterFooter',
                Data => {
                    %Param,
                    %PageNav,
                },
            );
        }
        for my $Key ( sort keys %NavBarFilter ) {
            if ( $AllTickets > $PageShown ) {
                $LayoutObject->Block(
                    Name => 'FilterFooterItem',
                    Data => {
                        %{ $NavBarFilter{$Key} },
                    },
                );
            }
        }

        # get the dynamic fields for this screen
        my $DynamicFieldObject = $Kernel::OM->Get('Kernel::System::DynamicField');
        my $BackendObject      = $Kernel::OM->Get('Kernel::System::DynamicField::Backend');

        # get dynamic field config for frontend module
        my $DynamicFieldFilter = $ConfigObject->Get("Ticket::Frontend::CustomerTicketOverview")->{DynamicField};
        my $DynamicField       = $DynamicFieldObject->DynamicFieldListGet(
            Valid       => 1,
            ObjectType  => ['Ticket'],
            FieldFilter => $DynamicFieldFilter || {},
        );

        # reduce the dynamic fields to only the ones that are desinged for customer interface
        my @CustomerDynamicFields;
        DYNAMICFIELD:
        for my $DynamicFieldConfig ( @{$DynamicField} ) {
            next DYNAMICFIELD if !IsHashRefWithData($DynamicFieldConfig);

            my $IsCustomerInterfaceCapable = $BackendObject->HasBehavior(
                DynamicFieldConfig => $DynamicFieldConfig,
                Behavior           => 'IsCustomerInterfaceCapable',
            );
            next DYNAMICFIELD if !$IsCustomerInterfaceCapable;

            push @CustomerDynamicFields, $DynamicFieldConfig;
        }
        $DynamicField = \@CustomerDynamicFields;

        # Dynamic fields
        # cycle trough the activated Dynamic Fields for this screen
        DYNAMICFIELD:
        for my $DynamicFieldConfig ( @{$DynamicField} ) {
            next DYNAMICFIELD if !IsHashRefWithData($DynamicFieldConfig);

            my $Label = $DynamicFieldConfig->{Label};

            # get field sortable condition
            my $IsSortable = $BackendObject->HasBehavior(
                DynamicFieldConfig => $DynamicFieldConfig,
                Behavior           => 'IsSortable',
            );

            if ($IsSortable) {
                my $CSS = '';
                if (
                    $SortBy
                    && ( $SortBy eq ( 'DynamicField_' . $DynamicFieldConfig->{Name} ) )
                    )
                {
                    if ( $OrderByCurrent && ( $OrderByCurrent eq 'Up' ) ) {
                        $OrderBy = 'Down';
                        $CSS .= ' SortDescending';
                    }
                    else {
                        $OrderBy = 'Up';
                        $CSS .= ' SortAscending';
                    }
                }

                $LayoutObject->Block(
                    Name => 'OverviewNavBarPageDynamicField',
                    Data => {
                        %Param,
                        CSS => $CSS,
                    },
                );

                $LayoutObject->Block(
                    Name => 'OverviewNavBarPageDynamicFieldSortable',
                    Data => {
                        %Param,
                        OrderBy          => $OrderBy,
                        Label            => $Label,
                        DynamicFieldName => $DynamicFieldConfig->{Name},
                        Filter           => $FilterCurrent,
                    },
                );

                # example of dynamic fields order customization
                $LayoutObject->Block(
                    Name => 'OverviewNavBarPageDynamicField_' . $DynamicFieldConfig->{Name},
                    Data => {
                        %Param,
                        CSS => $CSS,
                    },
                );

                $LayoutObject->Block(
                    Name => 'OverviewNavBarPageDynamicField_'
                        . $DynamicFieldConfig->{Name}
                        . '_Sortable',
                    Data => {
                        %Param,
                        OrderBy          => $OrderBy,
                        Label            => $Label,
                        DynamicFieldName => $DynamicFieldConfig->{Name},
                        Filter           => $FilterCurrent,
                    },
                );
            }
            else {

                $LayoutObject->Block(
                    Name => 'OverviewNavBarPageDynamicField',
                    Data => {
                        %Param,
                    },
                );

                $LayoutObject->Block(
                    Name => 'OverviewNavBarPageDynamicFieldNotSortable',
                    Data => {
                        %Param,
                        Label => $Label,
                    },
                );

                # example of dynamic fields order customization
                $LayoutObject->Block(
                    Name => 'OverviewNavBarPageDynamicField_' . $DynamicFieldConfig->{Name},
                    Data => {
                        %Param,
                    },
                );

                $LayoutObject->Block(
                    Name => 'OverviewNavBarPageDynamicField_'
                        . $DynamicFieldConfig->{Name}
                        . '_NotSortable',
                    Data => {
                        %Param,
                        Label => $Label,
                    },
                );
            }
        }

        my @ViewableTickets = $TicketObject->TicketSearch(
            %{ $Filters{ $Self->{Subaction} }->{$FilterCurrent}->{Search} },
            %SearchInArchive,
            Result => 'ARRAY',
        );

        # show tickets
        $Counter = 0;
        for my $TicketID (@ViewableTickets) {
            $Counter++;
            if (
                $Counter >= $StartHit
                && $Counter < ( $PageShown + $StartHit )
                )
            {
                $Self->ShowTicketStatus( TicketID => $TicketID );
            }
        }
    }

    # create & return output
    my $Title = $Self->{Subaction};
    if ( $Title eq 'MyTickets' ) {
        $Title = Translatable('My Tickets');
    }
    elsif ( $Title eq 'CompanyTickets' ) {
        $Title = Translatable('Company Tickets');
    }
    my $Refresh = '';
    if ( $Self->{UserRefreshTime} ) {
        $Refresh = 60 * $Self->{UserRefreshTime};
    }
    my $Output = $LayoutObject->CustomerHeader(
        Title   => $Title,
        Refresh => $Refresh,
    );

    # build NavigationBar
    $Output .= $LayoutObject->CustomerNavigationBar();
    $Output .= $LayoutObject->Output(
        TemplateFile => 'CustomerTicketOverview',
        Data         => \%Param,
    );

    # get page footer
    $Output .= $LayoutObject->CustomerFooter();

    # return page
    return $Output;
}

# ShowTicket
sub ShowTicketStatus {
    my ( $Self, %Param ) = @_;

    my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
    my $TicketObject = $Kernel::OM->Get('Kernel::System::Ticket');
    my $TicketID     = $Param{TicketID} || return;

    # contains last article (non-internal)
    my %Article;

    # get whole article index
    my @ArticleIDs = $TicketObject->ArticleIndex( TicketID => $Param{TicketID} );

    # get article data
    if (@ArticleIDs) {
        my %LastNonInternalArticle;

        ARTICLEID:
        for my $ArticleID ( reverse @ArticleIDs ) {
            my %CurrentArticle = $TicketObject->ArticleGet( ArticleID => $ArticleID );

            # check for non-internal and non-chat article
            next ARTICLEID if $CurrentArticle{ArticleType} =~ m{internal|chat}smx;

            # check for customer article
            if ( $CurrentArticle{SenderType} eq 'customer' ) {
                %Article = %CurrentArticle;
                last ARTICLEID;
            }

            # check for last non-internal article (sender type does not matter)
            if ( !%LastNonInternalArticle ) {
                %LastNonInternalArticle = %CurrentArticle;
            }
        }

        if ( !%Article && %LastNonInternalArticle ) {
            %Article = %LastNonInternalArticle;
        }
    }

    my $NoArticle;
    if ( !%Article ) {
        $NoArticle = 1;
    }

    # get ticket info
    my %Ticket = $TicketObject->TicketGet(
        TicketID      => $TicketID,
        DynamicFields => 0,
    );

    my $Subject;
    my $ConfigObject          = $Kernel::OM->Get('Kernel::Config');
    my $SmallViewColumnHeader = $ConfigObject->Get('Ticket::Frontend::CustomerTicketOverview')->{ColumnHeader};

    # check if last customer subject or ticket title should be shown
    if ( $SmallViewColumnHeader eq 'LastCustomerSubject' ) {
        $Subject = $Article{Subject} || '';
    }
    elsif ( $SmallViewColumnHeader eq 'TicketTitle' ) {
        $Subject = $Ticket{Title};
    }

    # return ticket information if there is no article
    if ($NoArticle) {
        $Article{State}        = $Ticket{State};
        $Article{TicketNumber} = $Ticket{TicketNumber};
        $Article{CustomerAge}  = $LayoutObject->CustomerAge(
            Age   => $Ticket{Age},
            Space => ' '
        ) || 0;
        $Article{Body} = $LayoutObject->{LanguageObject}->Translate('This item has no articles yet.');
    }

    # otherwise return article information
    else {
        $Article{CustomerAge} = $LayoutObject->CustomerAge(
            Age   => $Article{Age},
            Space => ' '
        ) || 0;
    }

    # customer info (customer name)
    if ( $Article{CustomerUserID} ) {
        $Param{CustomerName} = $Kernel::OM->Get('Kernel::System::CustomerUser')->CustomerName(
            UserLogin => $Article{CustomerUserID},
        );
        $Param{CustomerName} = '(' . $Param{CustomerName} . ')' if ( $Param{CustomerName} );
    }

    # if there is no subject try with Ticket title or set to Untitled
    if ( !$Subject ) {
        $Subject = $Ticket{Title} || Translatable('Untitled!');
    }

    # condense down the subject
    $Subject = $TicketObject->TicketSubjectClean(
        TicketNumber => $Article{TicketNumber},
        Subject      => $Subject,
    );

    $Param{CreatedBy} = $Kernel::OM->Get('Kernel::System::CustomerUser')->CustomerName(
        UserLogin => $Ticket{CreateBy},
    );

    # add block
    $LayoutObject->Block(
        Name => 'Record',
        Data => {
            %Article,
            %Ticket,
            Subject => $Subject,
            %Param,
        },
    );

    my $Owner = $ConfigObject->Get('Ticket::Frontend::CustomerTicketOverview')->{Owner};
    my $Queue = $ConfigObject->Get('Ticket::Frontend::CustomerTicketOverview')->{Queue};

    if ($Owner) {
        my $OwnerName = $Kernel::OM->Get('Kernel::System::User')->UserName( UserID => $Ticket{OwnerID} );
        $LayoutObject->Block(
            Name => 'RecordOwner',
            Data => {
                OwnerName => $OwnerName,
            },
        );
    }
    if ($Queue) {
        $LayoutObject->Block(
            Name => 'RecordQueue',
            Data => {
                %Ticket,
            },
        );
    }

    # get the dynamic fields for this screen
    my $DynamicFieldObject = $Kernel::OM->Get('Kernel::System::DynamicField');
    my $BackendObject      = $Kernel::OM->Get('Kernel::System::DynamicField::Backend');

    # get dynamic field config for frontend module
    my $DynamicFieldFilter = $ConfigObject->Get("Ticket::Frontend::CustomerTicketOverview")->{DynamicField};
    my $DynamicField       = $DynamicFieldObject->DynamicFieldListGet(
        Valid       => 1,
        ObjectType  => ['Ticket'],
        FieldFilter => $DynamicFieldFilter || {},
    );

    # reduce the dynamic fields to only the ones that are desinged for customer interface
    my @CustomerDynamicFields;
    DYNAMICFIELD:
    for my $DynamicFieldConfig ( @{$DynamicField} ) {
        next DYNAMICFIELD if !IsHashRefWithData($DynamicFieldConfig);

        my $IsCustomerInterfaceCapable = $BackendObject->HasBehavior(
            DynamicFieldConfig => $DynamicFieldConfig,
            Behavior           => 'IsCustomerInterfaceCapable',
        );
        next DYNAMICFIELD if !$IsCustomerInterfaceCapable;

        push @CustomerDynamicFields, $DynamicFieldConfig;
    }
    $DynamicField = \@CustomerDynamicFields;

    # Dynamic fields
    # cycle trough the activated Dynamic Fields for this screen
    DYNAMICFIELD:
    for my $DynamicFieldConfig ( @{$DynamicField} ) {
        next DYNAMICFIELD if !IsHashRefWithData($DynamicFieldConfig);

        # get field value
        my $Value = $BackendObject->ValueGet(
            DynamicFieldConfig => $DynamicFieldConfig,
            ObjectID           => $Ticket{TicketID},
        );

        my $ValueStrg = $BackendObject->DisplayValueRender(
            DynamicFieldConfig => $DynamicFieldConfig,
            Value              => $Value,
            ValueMaxChars      => 20,
            LayoutObject       => $LayoutObject,
        );

        $LayoutObject->Block(
            Name => 'RecordDynamicField',
            Data => {
                Value => $ValueStrg->{Value},
                Title => $ValueStrg->{Title},
            },
        );

        if ( $ValueStrg->{Link} ) {
            $LayoutObject->Block(
                Name => 'RecordDynamicFieldLink',
                Data => {
                    Value                       => $ValueStrg->{Value},
                    Title                       => $ValueStrg->{Title},
                    Link                        => $ValueStrg->{Link},
                    $DynamicFieldConfig->{Name} => $ValueStrg->{Title},
                },
            );
        }
        else {
            $LayoutObject->Block(
                Name => 'RecordDynamicFieldPlain',
                Data => {
                    Value => $ValueStrg->{Value},
                    Title => $ValueStrg->{Title},
                },
            );
        }

        # example of dynamic fields order customization
        $LayoutObject->Block(
            Name => 'RecordDynamicField' . $DynamicFieldConfig->{Name},
            Data => {
                Value => $ValueStrg->{Value},
                Title => $ValueStrg->{Title},
            },
        );

        if ( $ValueStrg->{Link} ) {
            $LayoutObject->Block(
                Name => 'RecordDynamicField' . $DynamicFieldConfig->{Name} . 'Link',
                Data => {
                    Value                       => $ValueStrg->{Value},
                    Title                       => $ValueStrg->{Title},
                    Link                        => $ValueStrg->{Link},
                    $DynamicFieldConfig->{Name} => $ValueStrg->{Title},
                },
            );
        }
        else {
            $LayoutObject->Block(
                Name => 'RecordDynamicField' . $DynamicFieldConfig->{Name} . 'Plain',
                Data => {
                    Value => $ValueStrg->{Value},
                    Title => $ValueStrg->{Title},
                },
            );
        }
    }
}

1;
It seems to me, like the custom files are not getting loaded?
OTRS 6.0.5
RStraub
Znuny guru
Posts: 2210
Joined: 13 Mar 2014, 09:16
Znuny Version: 6.0.14
Real Name: Rolf Straub

Re: Adding customer name in Customer ticket overview

Post by RStraub »

Hey there,

so I tried to do this on my test system and ran into this problem: OTRS does not log the CustomerUser (ID) of the customer creating a ticket. Customer tickets are always created from "root@localhost" it seems.

To get the first customer user who created the ticket, I parsed the history lines and took the first CustomerUser which got set. To do so, use this code in your perl code INSTEAD of the one posted earlier (same position though):

Code: Select all

    my @HistoryLines = $TicketObject->HistoryGet(
        TicketID => $Ticket{TicketID},
        UserID   => $Self->{UserID},
    );
    my @HistorySorted = sort { $a->{CreateTime} cmp $b->{CreateTime} } @HistoryLines;
    my $FirstCustomerUser;
    foreach my $Line ( @HistorySorted ) {
        if ($Line->{Name} =~ m/CustomerID=.*CustomerUser=.*/ ) {
            my @LineParts = split /[=;]+/, $Line->{Name};
            $FirstCustomerUser = $LineParts[3];
            last;
        }
    }
    $Param{CreatedBy} = $Kernel::OM->Get('Kernel::System::CustomerUser')->CustomerName(
        UserLogin => $FirstCustomerUser,
    );
On my test system this works.


Now, you said you don't see changes. Do you atleast see a new header in the table?
HeaderScreenshot.PNG
Are you using Addons that might modify your frontend, especially KIX or something?
You do not have the required permissions to view the files attached to this post.
Currently using: OTRS 6.0.14 -- MariaDB -- Ubuntu 16 LTS
JHS
Znuny newbie
Posts: 25
Joined: 13 Oct 2016, 11:22
Znuny Version: 6 PL 4

Re: Adding customer name in Customer ticket overview

Post by JHS »

Well, when I was first figuring out which file needed to be edited (either ~/Kernel/... or in ~/Custom/Kernel/...) it wasn't working when the modified file was in ~/Custom/Kernel/..., but then I copied those files to ~/Kernel/... and it showed an extra column, but with no data.

Since you replied that the custom pages need to be in the ~/Custom/Kernel/... directory, I haven't moved them from there, but now I do not see an extra column.
I'm not using any addons, the only custom thing about my OTRS installation is this :)

Thanks for helping me, I really appreciate it!
I'm gonna try your new script (I hope today) and I'll let you know.

Just to be sure, are my directories ok, I'm starting to doubt myself :o ?
[*]/opt/otrs/Custom/Kernel/Output/HTML/Templates/Standard/CustomerTicketOverview.tt
[*]/opt/otrs/Custom/Kernel/Modules/CustomerTicketOverview.pm
Last edited by JHS on 07 Aug 2017, 14:55, edited 2 times in total.
OTRS 6.0.5
JHS
Znuny newbie
Posts: 25
Joined: 13 Oct 2016, 11:22
Znuny Version: 6 PL 4

Re: Adding customer name in Customer ticket overview

Post by JHS »

Hello

I've added your new code in the CustomerTicketOverview.pm file under ~/Custom/Kernel/...
I could not check it because there was no extra column added in the overview.

Just out of curiosity I copied my template from ~/Custom/Kernel/... to ~/Kernel/... and restarted apache, and now I can see the extra column:
CustomerTicketOverview.png
Out of more curiosity, I copied the .pm file from ~/Custom/Kernel/... to ~/Kernel/... and restarted apache, and now I can see exactly what I wanted:
CustomerTicketOverview-createdby.png


So your new code works, but for some reason, OTRS does not seem to load the files in the ~/Custom/Kernel/... directory.
Any idea's why not?
I've already checked the files privileges, owned by OTRS and chmod 660 (for CustomerTicketOverview.tt and .pm)
Just to be sure, are my directories ok, I'm starting to doubt myself :o ?

Code: Select all

/opt/otrs/Custom/Kernel/Output/HTML/Templates/Standard/CustomerTicketOverview.tt
/opt/otrs/Custom/Kernel/Modules/CustomerTicketOverview.pm
EDIT:Nevermind, I found the issue, apparently the directories under the ~/otrs/Custom directory did not have the correct privileges.
Did a chmod 775 for all the directories under ~/otrs/Custom and then an apache restart and this fixed it!

So now I have what I wanted!
Thank you very much for assisting me in this matter!
You do not have the required permissions to view the files attached to this post.
OTRS 6.0.5
RStraub
Znuny guru
Posts: 2210
Joined: 13 Mar 2014, 09:16
Znuny Version: 6.0.14
Real Name: Rolf Straub

Re: Adding customer name in Customer ticket overview

Post by RStraub »

Yey, great it works!

Doesn't it feel good to hack the OTRS ;) ?
Currently using: OTRS 6.0.14 -- MariaDB -- Ubuntu 16 LTS
JHS
Znuny newbie
Posts: 25
Joined: 13 Oct 2016, 11:22
Znuny Version: 6 PL 4

Re: Adding customer name in Customer ticket overview

Post by JHS »

RStraub wrote:Yey, great it works!

Doesn't it feel good to hack the OTRS ;) ?
Yeah, it does, once it works, its awesome!
OTRS 6.0.5
JHS
Znuny newbie
Posts: 25
Joined: 13 Oct 2016, 11:22
Znuny Version: 6 PL 4

Re: Adding customer name in Customer ticket overview

Post by JHS »

I actually did notice something that might be handy for our customers. When they click the "createdby" header to sort, they are forwarded to the: "welcome, create your first ticket" page instead of sorting by the "createdby" value

Is there a way to add this function like with the default columns (state, age, etc...)?
OTRS 6.0.5
savoir81
Znuny newbie
Posts: 4
Joined: 09 Oct 2017, 16:53
Znuny Version: 5.0.0.13

Re: Adding customer name in Customer ticket overview

Post by savoir81 »

Hi Guys,

I am having the same "problem". I would also like to insert 2 new columns,
Customer ticket owner(not creator of the ticket, but the customer owner of the ticket) and
Ticket creation date(Instead of ticket AGE).

Is this possible to do it?

Also when you said that the owner of all tickets is roos@localhost, how is then possible that in db table TICKET there is column CUSTOMER_USER_ID with the id of the customer?

Regards and thanks,
Savo
RStraub
Znuny guru
Posts: 2210
Joined: 13 Mar 2014, 09:16
Znuny Version: 6.0.14
Real Name: Rolf Straub

Re: Adding customer name in Customer ticket overview

Post by RStraub »

Hey savoir,

the db-column is the customer the ticket is ASSIGNED to. But it's not the customer that created the ticket. Since you can change customers after ticket creation these might be different values. That's why I parsed the history lines to see who the first customer is that got assigned.

Where are you struggling when inserting creation date and/or owner?
Currently using: OTRS 6.0.14 -- MariaDB -- Ubuntu 16 LTS
Post Reply