1# --
2# Copyright (C) 2001-2020 OTRS AG, https://otrs.com/
3# --
4# This software comes with ABSOLUTELY NO WARRANTY. For details, see
5# the enclosed file COPYING for license information (GPL). If you
6# did not receive this file, see https://www.gnu.org/licenses/gpl-3.0.txt.
7# --
8
9## no critic (Modules::RequireExplicitPackage)
10use strict;
11use warnings;
12use utf8;
13
14use vars (qw($Self));
15
16# Broken on certain Perl 5.28 versions due to a Perl crash that we can't work around.
17my @BlacklistPerlVersions = (
18    v5.26.1,
19    v5.26.3,
20    v5.28.1,
21    v5.28.2,
22    v5.30.0,
23    v5.30.1,
24    v5.30.2,
25    v5.30.3,
26);
27
28if ( grep { $^V eq $_ } @BlacklistPerlVersions ) {
29    $Self->True( 1, "Current Perl version $^V is known to be buggy for this test, skipping." );
30    return 1;
31}
32
33$Kernel::OM->ObjectParamAdd(
34    'Kernel::System::UnitTest::Helper' => {
35        RestoreDatabase => 1,
36    },
37);
38my $Helper = $Kernel::OM->Get('Kernel::System::UnitTest::Helper');
39
40my $ConfigObject = $Kernel::OM->Get('Kernel::Config');
41$ConfigObject->Set(
42    Key   => 'Ticket::NumberGenerator',
43    Value => 'Kernel::System::Ticket::Number::AutoIncrement',
44);
45$ConfigObject->Set(
46    Key   => 'Ticket::NumberGenerator::AutoIncrement::MinCounterSize',
47    Value => 5,
48);
49$ConfigObject->Set(
50    Key   => 'SystemID',
51    Value => 10,
52);
53
54# Delete counters
55my $Success = $Kernel::OM->Get('Kernel::System::DB')->Do(
56    SQL => 'DELETE FROM ticket_number_counter',
57);
58$Self->True(
59    $Success,
60    'Temporary cleared ticket_nuber_counter table',
61);
62
63my $TicketNumberGeneratorObject = $Kernel::OM->Get('Kernel::System::Ticket::Number::AutoIncrement');
64
65# Create a new ticket and get it in order to influence its cache
66my $TicketObject = $Kernel::OM->Get('Kernel::System::Ticket');
67my $TicketID     = $TicketObject->TicketCreate(
68    Title        => 'Some Ticket Title',
69    QueueID      => 1,
70    Lock         => 'unlock',
71    PriorityID   => 3,
72    StateID      => 4,
73    TypeID       => 1,
74    CustomerID   => '123465',
75    CustomerUser => 'customer@example.com',
76    OwnerID      => 1,
77    UserID       => 1,
78);
79my %Ticket = $TicketObject->TicketGet(
80    TicketID      => $TicketID,
81    DynamicFields => 0,
82    UserID        => 1,
83    Silent        => 0,
84);
85my $CacheKey  = "Cache::GetTicket$TicketID";
86my $CacheType = 'Ticket';
87
88my $SystemID = $ConfigObject->Get('SystemID');
89
90# Remove SystemID  and all zeros
91my $ExpectedValue = $Ticket{TicketNumber};
92$ExpectedValue =~ s{\A $SystemID 0* }{}msx;
93$ExpectedValue++;
94
95# Test InitialCounterOffsetCalculate()
96my $InitialCounteOffset = $TicketNumberGeneratorObject->InitialCounterOffsetCalculate();
97$Self->Is(
98    $InitialCounteOffset,
99    $ExpectedValue,
100    "InitialCounterOffsetCalculate() - Normal last ticket"
101);
102
103my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache');
104$CacheObject->CleanUp();
105
106# Remove ticket number InitialCounterOffsetCalculate should be 1
107$CacheObject->Set(
108    Type  => $CacheType,
109    Key   => $CacheKey,
110    Value => {
111        %Ticket,
112        TicketNumber => '',
113    },
114    TTL => 60 * 60 * 24 * 20,
115);
116$InitialCounteOffset = $TicketNumberGeneratorObject->InitialCounterOffsetCalculate();
117$Self->Is(
118    $InitialCounteOffset,
119    1,
120    "InitialCounterOffsetCalculate() - Last ticket without TicketNumber"
121);
122
123$CacheObject->CleanUp();
124
125# Set ticket number to invalid for InitialCounterOffsetCalculate() by using only SytemID and 0s
126#   that are removed by the function.
127$CacheObject->Set(
128    Type  => $CacheType,
129    Key   => $CacheKey,
130    Value => {
131        %Ticket,
132        TicketNumber => $SystemID . '00',
133    },
134    TTL => 60 * 60 * 24 * 20,
135);
136$InitialCounteOffset = $TicketNumberGeneratorObject->InitialCounterOffsetCalculate();
137$Self->Is(
138    $InitialCounteOffset,
139    1,
140    "InitialCounterOffsetCalculate() - Last ticket with invalid TicketNumber"
141);
142
143# Set ticket number to a date based one for InitialCounterOffsetCalculate()
144$CacheObject->Set(
145    Type  => $CacheType,
146    Key   => $CacheKey,
147    Value => {
148        %Ticket,
149        TicketNumber => 201705031069,
150    },
151    TTL => 60 * 60 * 24 * 20,
152);
153$InitialCounteOffset = $TicketNumberGeneratorObject->InitialCounterOffsetCalculate();
154$Self->Is(
155    $InitialCounteOffset,
156    1,
157    "InitialCounterOffsetCalculate() - Last ticket with date based TicketNumber"
158);
159
160my @Tests = (
161    {
162        TN => 9_999_999_999_000_000,
163    },
164    {
165        TN => 9_999_999_999_999_000,
166    },
167);
168
169for my $Test (@Tests) {
170
171    my $TicketID = $TicketObject->TicketCreate(
172        TN           => $Test->{TN},
173        Title        => 'Some Ticket Title',
174        QueueID      => 1,
175        Lock         => 'unlock',
176        PriorityID   => 3,
177        StateID      => 4,
178        TypeID       => 1,
179        CustomerID   => '123465',
180        CustomerUser => 'customer@example.com',
181        OwnerID      => 1,
182        UserID       => 1,
183    );
184}
185$InitialCounteOffset = $TicketNumberGeneratorObject->InitialCounterOffsetCalculate();
186$Self->Is(
187    $InitialCounteOffset,
188    9_999_999_999_999_001,
189    "InitialCounterOffsetCalculate() after ticket creation"
190);
191
192# TicketNumberBuild() tests
193$TicketID = $TicketObject->TicketCreate(
194    TN           => 123,
195    Title        => 'Some Ticket Title',
196    QueueID      => 1,
197    Lock         => 'unlock',
198    PriorityID   => 3,
199    StateID      => 4,
200    TypeID       => 1,
201    CustomerID   => '123465',
202    CustomerUser => 'customer@example.com',
203    OwnerID      => 1,
204    UserID       => 1,
205);
206
207my $TicketNumber = $TicketNumberGeneratorObject->TicketNumberBuild();
208
209# Get last ticket number counter.
210my $DBObject = $Kernel::OM->Get('Kernel::System::DB');
211return if !$DBObject->Prepare(
212    SQL => 'SELECT MAX(counter) FROM ticket_number_counter',
213);
214my $Counter;
215while ( my @Data = $DBObject->FetchrowArray() ) {
216    $Counter = $Data[0];
217}
218
219# Set the expected value
220my $MinSize = $ConfigObject->Get('Ticket::NumberGenerator::AutoIncrement::MinCounterSize');
221$Counter       = sprintf "%.*u", $MinSize, $Counter;
222$ExpectedValue = $SystemID . $Counter;
223
224$Self->Is(
225    $TicketNumber,
226    $ExpectedValue,
227    "TicketNumberBuild() with counters",
228);
229
230# Delete current counters.
231return if !$DBObject->Do(
232    SQL => 'DELETE FROM ticket_number_counter',
233);
234$Kernel::OM->Get('Kernel::System::Cache')->CleanUp();
235
236$TicketNumber  = $TicketNumberGeneratorObject->TicketNumberBuild();
237$Counter       = sprintf "%.*u", $MinSize, 124;
238$ExpectedValue = $SystemID . $Counter;
239$Self->Is(
240    $TicketNumber,
241    $ExpectedValue,
242    "TicketNumberBuild() without counters",
243);
244
245# _LooksLikeDateBasedTicketNumber tests
246
247@Tests = (
248    {
249        Name           => 'Empty',
250        TicketNumber   => '',
251        ExpectedResult => 0,
252    },
253    {
254        Name           => 'Short Number',
255        TicketNumber   => 1234567,
256        ExpectedResult => 0,
257    },
258    {
259        Name           => 'Large Number',
260        TicketNumber   => 123456789,
261        ExpectedResult => 0,
262    },
263    {
264        Name           => 'Correct Length Number',
265        TicketNumber   => 12345678,
266        ExpectedResult => 0,
267    },
268    {
269        Name           => 'Short Date',
270        TicketNumber   => 2017020,
271        ExpectedResult => 0,
272    },
273    {
274        Name           => 'Large Date',
275        TicketNumber   => 2017050302,
276        ExpectedResult => 1,
277    },
278    {
279        Name           => 'Correct Length Date',
280        TicketNumber   => 20120503,
281        ExpectedResult => 1,
282    },
283    {
284        Name           => 'Wrong Date',
285        TicketNumber   => 2016023112,
286        ExpectedResult => 0,
287    },
288);
289
290for my $Test (@Tests) {
291    my $Result = $TicketNumberGeneratorObject->_LooksLikeDateBasedTicketNumber( $Test->{TicketNumber} );
292
293    $Self->Is(
294        $Result // 0,
295        $Test->{ExpectedResult},
296        "$Test->{Name} _LooksLikeDateBasedTicketNumber()",
297    );
298}
299
300# Cleanup is done by RestoreDatabase.
301
3021;
303