Bug 17855: perltidy onboarding.pl
[koha.git] / installer / onboarding.pl
1 #!/usr/bin/perl
2
3 # This file is part of Koha.
4 #
5 # Copyright (C) 2017 Catalyst IT
6 #
7 # Koha is free software; you can redistribute it and/or modify it
8 # under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 3 of the License, or
10 # (at your option) any later version.
11 #
12 # Koha is distributed in the hope that it will be useful, but
13 # WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
16 #
17 # You should have received a copy of the GNU General Public License
18 # along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20 #Recommended pragmas
21 use Modern::Perl;
22 use diagnostics;
23 use C4::InstallAuth;
24 use CGI qw ( -utf8 );
25 use C4::Output;
26 use C4::Members;
27 use Koha::Patrons;
28 use Koha::Libraries;
29 use Koha::Database;
30 use Koha::DateUtils;
31 use Koha::Patron::Categories;
32 use Koha::Patron::Category;
33 use Koha::ItemTypes;
34 use Koha::IssuingRule;
35 use Koha::IssuingRules;
36
37 #Setting variables
38 my $input = new CGI;
39 my $step  = $input->param('step');
40
41 #Getting the appropriate template to display to the user
42 my ( $template, $loggedinuser, $cookie ) =
43   C4::InstallAuth::get_template_and_user(
44     {
45         template_name => "/onboarding/onboardingstep"
46           . ( $step ? $step : 1 ) . ".tt",
47         query           => $input,
48         type            => "intranet",
49         authnotrequired => 0,
50         debug           => 1,
51     }
52   );
53
54 #Check database connection
55 my %info;
56 $info{'dbname'} = C4::Context->config("database");
57 $info{'dbms'}   = (
58       C4::Context->config("db_scheme")
59     ? C4::Context->config("db_scheme")
60     : "mysql"
61 );
62
63 $info{'hostname'} = C4::Context->config("hostname");
64 $info{'port'}     = C4::Context->config("port");
65 $info{'user'}     = C4::Context->config("user");
66 $info{'password'} = C4::Context->config("pass");
67 my $dbh = DBI->connect(
68     "DBI:$info{dbms}:dbname=$info{dbname};host=$info{hostname}"
69       . ( $info{port} ? ";port=$info{port}" : "" ),
70     $info{'user'}, $info{'password'}
71 );
72
73 #Store the value of the template input name='op' in the variable $op so we can check if the user has pressed the button with the name="op" and value="finish" meaning the user has finished the onboarding tool.
74 my $op = $input->param('op') || '';
75 $template->param( 'op' => $op );
76
77 my $schema = Koha::Database->new()->schema();
78
79 if ( $op && $op eq 'finish' )
80 { #If the value of $op equals 'finish' then redirect user to /cgi-bin/koha/mainpage.pl
81     print $input->redirect("/cgi-bin/koha/mainpage.pl");
82     exit;
83 }
84
85 my $libraries = Koha::Libraries->search( {}, { order_by => ['branchcode'] }, );
86 $template->param(
87     libraries   => $libraries,
88     group_types => [
89         {
90             categorytype => 'searchdomain',
91             categories   => [
92                 Koha::LibraryCategories->search(
93                     { categorytype => 'searchdomain' }
94                 )
95             ],
96         },
97         {
98             categorytype => 'properties',
99             categories   => [
100                 Koha::LibraryCategories->search(
101                     { categorytype => 'properties' }
102                 )
103             ],
104         },
105     ]
106 );
107
108 #Select all the patron category records in the categories database table and give them to the template
109 my $categories = Koha::Patron::Categories->search();
110 $template->param( 'categories' => $categories, );
111
112 #Check if the $step variable equals 1 i.e. the user has clicked to create a library in the create library screen 1
113 my $itemtypes = Koha::ItemTypes->search();
114 $template->param( 'itemtypes' => $itemtypes, );
115
116 if ( $step && $step == 1 ) {
117
118     #store inputted parameters in variables
119     my $branchcode = $input->param('branchcode');
120     $branchcode = uc($branchcode);
121     my $categorycode = $input->param('categorycode');
122     my $op = $input->param('op') || 'list';
123     my $message;
124     my $library;
125
126     #Take the text 'branchname' and store it in the @fields array
127     my @fields = qw(
128       branchname
129     );
130
131     $template->param( 'branchcode' => $branchcode );
132     $branchcode =~ s|\s||g
133       ; # Use a regular expression to check the value of the inputted branchcode
134
135 #Create a new library object and store the branchcode and @fields array values in this new library object
136     $library = Koha::Library->new(
137         {
138             branchcode => $branchcode,
139             ( map { $_ => scalar $input->param($_) || undef } @fields )
140         }
141     );
142
143     eval { $library->store; }; #Use the eval{} function to store the library object
144     if ($library) {
145         $message = 'success_on_insert';
146     }
147     else {
148         $message = 'error_on_insert';
149     }
150     $template->param( 'message' => $message );
151
152 #Check if the $step variable equals 2 i.e. the user has clicked to create a patron category in the create patron category screen 1
153 }
154 elsif ( $step && $step == 2 ) {
155     if ( $op eq "add_validate_category" ) {
156
157         #Initialising values
158         my $searchfield  = $input->param('description') // q||;
159         my $categorycode = $input->param('categorycode');
160         my $op           = $input->param('op') // 'list';
161         my $message;
162         my $category;
163         $template->param( 'categorycode' => $categorycode );
164
165         my ( $template, $loggedinuser, $cookie ) =
166           C4::InstallAuth::get_template_and_user(
167             {
168                 template_name   => "/onboarding/onboardingstep2.tt",
169                 query           => $input,
170                 type            => "intranet",
171                 authnotrequired => 0,
172                 flagsrequired =>
173                   { parameters => 'parameters_remaining_permissions' },
174                 debug => 1,
175             }
176           );
177
178       #Once the user submits the page, this code validates the input and adds it
179       #to the database as a new patron category
180         $categorycode = $input->param('categorycode');
181         my $description           = $input->param('description');
182         my $overduenoticerequired = $input->param('overduenoticerequired');
183         my $category_type         = $input->param('category_type');
184         my $default_privacy       = $input->param('default_privacy');
185         my $enrolmentperiod       = $input->param('enrolmentperiod');
186         my $enrolmentperioddate = $input->param('enrolmentperioddate') || undef;
187
188         #Converts the string into a date format
189         if ($enrolmentperioddate) {
190             $enrolmentperioddate = output_pref(
191                 {
192                     dt         => dt_from_string($enrolmentperioddate),
193                     dateformat => 'DateTime',
194                     dateonly   => 1,
195                 }
196             );
197         }
198
199         #Adds a new patron category to the database
200         $category = Koha::Patron::Category->new(
201             {
202                 categorycode          => $categorycode,
203                 description           => $description,
204                 overduenoticerequired => $overduenoticerequired,
205                 category_type         => $category_type,
206                 default_privacy       => $default_privacy,
207                 enrolmentperiod       => $enrolmentperiod,
208                 enrolmentperioddate   => $enrolmentperioddate
209             }
210         );
211
212         eval { $category->store; };
213
214         #Error messages
215         if ($category) {
216             $message = 'success_on_insert';
217         }
218         else {
219             $message = 'error_on_insert';
220         }
221
222         $template->param( 'message' => $message );
223     }
224
225     #Create a patron
226 }
227 elsif ( $step && $step == 3 ) {
228     my $firstpassword  = $input->param('password')  || '';
229     my $secondpassword = $input->param('password2') || '';
230
231     #Find all patron records in the database and hand them to the template
232     my %currentpatrons = Koha::Patrons->search();
233     my $currentpatrons = values %currentpatrons;
234     $template->param( 'patrons' => $currentpatrons );
235
236 #Find all library records in the database and hand them to the template to display in the library dropdown box
237     my $libraries =
238       Koha::Libraries->search( {}, { order_by => ['branchcode'] }, );
239     $template->param(
240         libraries   => $libraries,
241         group_types => [
242             {
243                 categorytype => 'searchdomain',
244                 categories   => [
245                     Koha::LibraryCategories->search(
246                         { categorytype => 'searchdomain' }
247                     )
248                 ],
249             },
250             {
251                 categorytype => 'properties',
252                 categories   => [
253                     Koha::LibraryCategories->search(
254                         { categorytype => 'properties' }
255                     )
256                 ],
257             },
258         ]
259     );
260
261 #Find all patron categories in the database and hand them to the template to display in the patron category dropdown box
262     my $categories = Koha::Patron::Categories->search();
263     $template->param( 'categories' => $categories, );
264
265 #Incrementing the highest existing patron cardnumber to prevent duplicate cardnumber entry
266
267     my $existing_cardnumber =
268       $schema->resultset('Borrower')->get_column('cardnumber')->max() // 0;
269
270     my $new_cardnumber = $existing_cardnumber + 1;
271     $template->param( "newcardnumber" => $new_cardnumber );
272
273     my $op = $input->param('op') // 'list';
274     my $minpw = C4::Context->preference("minPasswordLength");
275     $template->param( "minPasswordLength" => $minpw );
276     my @messages;
277     my @errors;
278     my $nok            = $input->param('nok');
279     my $cardnumber     = $input->param('cardnumber');
280     my $borrowernumber = $input->param('borrowernumber');
281     my $userid         = $input->param('userid');
282
283     # function to designate mandatory fields (visually with css)
284     my $check_BorrowerMandatoryField =
285       C4::Context->preference("BorrowerMandatoryField");
286     my @field_check = split( /\|/, $check_BorrowerMandatoryField );
287     foreach (@field_check) {
288         $template->param( "mandatory$_" => 1 );
289         $template->param(
290             BorrowerMandatoryField =>
291               C4::Context->preference("BorrowerMandatoryField")
292             ,    #field to test with javascript
293         );
294     }
295
296  #If the entered cardnumber causes an error hand this error to the @errors array
297     if ( my $error_code = checkcardnumber( $cardnumber, $borrowernumber ) ) {
298         push @errors,
299             $error_code == 1 ? 'ERROR_cardnumber_already_exists'
300           : $error_code == 2 ? 'ERROR_cardnumber_length'
301           :                    ();
302     }
303
304    #If the entered password causes an error hand this error to the @errors array
305     push @errors, "ERROR_password_mismatch"
306       if $firstpassword ne $secondpassword;
307     push @errors, "ERROR_short_password"
308       if ( $firstpassword
309         && $minpw
310         && $firstpassword ne '****'
311         && ( length($firstpassword) < $minpw ) );
312
313     #Passing errors to template
314     $nok = $nok || scalar(@errors);
315
316 #If errors have been generated from the users inputted cardnumber or password then display the error and do not insert the patron into the borrowers table
317     if ($nok) {
318         foreach my $error (@errors) {
319             if ( $error eq 'ERROR_password_mismatch' ) {
320                 $template->param( errorpasswordmismatch => 1 );
321             }
322             if ( $error eq 'ERROR_login_exist' ) {
323                 $template->param( errorloginexists => 1 );
324             }
325             if ( $error eq 'ERROR_cardnumber_already_exists' ) {
326                 $template->param( errorcardnumberexists => 1 );
327             }
328             if ( $error eq 'ERROR_cardnumber_length' ) {
329                 $template->param( errorcardnumberlength => 1 );
330             }
331             if ( $error eq 'ERROR_short_password' ) {
332                 $template->param( errorshortpassword => 1 );
333             }
334         }
335         $template->param( 'nok' => 1 );
336
337 #Else if no errors have been caused by the users inputted card number or password then insert the patron into the borrowers table
338     }
339     else {
340         my ( $template, $loggedinuser, $cookie ) =
341           C4::InstallAuth::get_template_and_user(
342             {
343                 template_name   => "/onboarding/onboardingstep3.tt",
344                 query           => $input,
345                 type            => "intranet",
346                 authnotrequired => 0,
347                 flagsrequired   => { borrowers => 1 },
348                 debug           => 1,
349             }
350           );
351
352         if ( $op eq 'add_validate' ) {
353             my %newdata;
354
355             #Store the template form values in the newdata hash
356             $newdata{borrowernumber} = $input->param('borrowernumber');
357             $newdata{surname}        = $input->param('surname');
358             $newdata{firstname}      = $input->param('firstname');
359             $newdata{cardnumber}     = $input->param('cardnumber');
360             $newdata{branchcode}     = $input->param('libraries');
361             $newdata{categorycode}   = $input->param('categorycode_entry');
362             $newdata{userid}         = $input->param('userid');
363             $newdata{password}       = $input->param('password');
364             $newdata{password2}      = $input->param('password2');
365             $newdata{privacy}        = "default";
366             $newdata{address}        = "";
367             $newdata{city}           = "";
368
369 #Hand tne the dateexpiry of the patron based on the patron category it is created from
370             my $patron_category =
371               Koha::Patron::Categories->find( $newdata{categorycode} );
372             $newdata{dateexpiry} =
373               $patron_category->get_expiry_date( $newdata{dateenrolled} );
374
375 #Hand the newdata hash to the AddMember subroutine in the C4::Members module and it creates a patron and hands back a borrowernumber which is being stored
376             my $borrowernumber = &AddMember(%newdata);
377
378 #Create a hash named member2 and fill it with the borrowernumber of the borrower that has just been created
379             my %member2;
380             $member2{'borrowernumber'} = $borrowernumber;
381
382 #Perform data validation on the flag that has been handed to onboarding.pl by the template
383             my $flag = $input->param('flag');
384             if ( $input->param('newflags') ) {
385                 my $dbh              = C4::Context->dbh();
386                 my @perms            = $input->multi_param('flag');
387                 my %all_module_perms = ();
388                 my %sub_perms        = ();
389                 foreach my $perm (@perms) {
390                     if ( $perm !~ /:/ ) {
391                         $all_module_perms{$perm} = 1;
392                     }
393                     else {
394                         my ( $module, $sub_perm ) = split /:/, $perm, 2;
395                         push @{ $sub_perms{$module} }, $sub_perm;
396                     }
397                 }
398
399                 # construct flags
400                 my @userflags = $schema->resultset('Userflag')->search(
401                     {},
402                     {
403                         order_by => { -asc => 'bit' },
404                     }
405                 );
406
407                 #Setting superlibrarian permissions for new patron
408                 my $flags =
409                   Koha::Patrons->find($borrowernumber)->set( { flags => 1 } )
410                   ->store;
411
412                 #Error handling checking if the patron was created successfully
413                 if ( !$borrowernumber ) {
414                     push @messages,
415                       { type => 'error', code => 'error_on_insert' };
416                 }
417                 else {
418                     push @messages,
419                       { type => 'message', code => 'success_on_insert' };
420                 }
421             }
422         }
423     }
424 }
425 elsif ( $step && $step == 4 ) {
426     my ( $template, $borrowernumber, $cookie ) =
427       C4::InstallAuth::get_template_and_user(
428         {
429             template_name   => "/onboarding/onboardingstep4.tt",
430             query           => $input,
431             type            => "intranet",
432             authnotrequired => 0,
433             flagsrequired =>
434               { parameters => 'parameters_remaining_permissions' },
435             debug => 1,
436         }
437       );
438     if ( $op eq "add_validate" ) {
439         my $description   = $input->param('description');
440         my $itemtype_code = $input->param('itemtype');
441         $itemtype_code = uc($itemtype_code);
442
443   #Create a new itemtype object using the user inputted itemtype and description
444         my $itemtype = Koha::ItemType->new(
445             {
446                 itemtype    => $itemtype_code,
447                 description => $description,
448             }
449         );
450         eval { $itemtype->store; };
451         my $message;
452
453 #Fill the $message variable with an error if the item type object was not successfully created and inserted into the itemtypes table
454         if ($itemtype) {
455             $message = 'success_on_insert';
456         }
457         else {
458             $message = 'error_on_insert';
459         }
460         $template->param( 'message' => $message );
461     }
462 }
463 elsif ( $step && $step == 5 ) {
464
465   #Find all the existing categories to display in a dropdown box in the template
466     my $categories;
467     $categories = Koha::Patron::Categories->search();
468     $template->param( categories => $categories, );
469
470  #Find all the exisiting item types to display in a dropdown box in the template
471     my $itemtypes;
472     $itemtypes = Koha::ItemTypes->search();
473     $template->param( itemtypes => $itemtypes, );
474
475   #Find all the exisiting libraries to display in a dropdown box in the template
476     my $libraries =
477       Koha::Libraries->search( {}, { order_by => ['branchcode'] }, );
478     $template->param(
479         libraries   => $libraries,
480         group_types => [
481             {
482                 categorytype => 'searchdomain',
483                 categories   => [
484                     Koha::LibraryCategories->search(
485                         { categorytype => 'searchdomain' }
486                     )
487                 ],
488             },
489             {
490                 categorytype => 'properties',
491                 categories   => [
492                     Koha::LibraryCategories->search(
493                         { categorytype => 'properties' }
494                     )
495                 ],
496             },
497         ]
498     );
499
500     my $input = CGI->new;
501     my $dbh   = C4::Context->dbh;
502
503     my ( $template, $loggedinuser, $cookie ) =
504       C4::InstallAuth::get_template_and_user(
505         {
506             template_name   => "/onboarding/onboardingstep5.tt",
507             query           => $input,
508             type            => "intranet",
509             authnotrequired => 0,
510             flagsrequired   => { parameters => 'manage_circ_rules' },
511             debug           => 1,
512         }
513       );
514
515     #If no libraries exist then set the $branch value to *
516     my $branch = $input->param('branch');
517     unless ($branch) {
518         if ( C4::Context->preference('DefaultToLoggedInLibraryCircRules') ) {
519             $branch =
520               Koha::Libraries->search->count() == 1
521               ? undef
522               : C4::Context::mybranch();
523         }
524         else {
525             $branch =
526               C4::Context::only_my_library()
527               ? ( C4::Context::mybranch() || '*' )
528               : '*';
529         }
530     }
531     $branch = '*' if $branch eq 'NO_LIBRARY_SET';
532     my $op = $input->param('op') || q{};
533
534     if ( $op eq 'add_validate' ) {
535         my $type            = $input->param('type');
536         my $br              = $input->param('branch');
537         my $bor             = $input->param('categorycode');
538         my $itemtype        = $input->param('itemtype');
539         my $maxissueqty     = $input->param('maxissueqty');
540         my $issuelength     = $input->param('issuelength');
541         my $lengthunit      = $input->param('lengthunit');
542         my $renewalsallowed = $input->param('renewalsallowed');
543         my $renewalperiod   = $input->param('renewalperiod');
544         my $onshelfholds    = $input->param('onshelfholds') || 0;
545         $maxissueqty =~ s/\s//g;
546         $maxissueqty = undef if $maxissueqty !~ /^\d+/;
547         $issuelength = $issuelength eq q{} ? undef : $issuelength;
548
549         my $params = {
550             branchcode      => $br,
551             categorycode    => $bor,
552             itemtype        => $itemtype,
553             maxissueqty     => $maxissueqty,
554             renewalsallowed => $renewalsallowed,
555             renewalperiod   => $renewalperiod,
556             issuelength     => $issuelength,
557             lengthunit      => $lengthunit,
558             onshelfholds    => $onshelfholds,
559         };
560
561         my @messages;
562
563 #Allows for the 'All' option to work when selecting all libraries for a circulation rule to apply to.
564         if ( $branch eq "*" ) {
565             my $search_default_rules =
566               $schema->resultset('DefaultCircRule')->count();
567             my $insert_default_rules =
568               $schema->resultset('Issuingrule')
569               ->new(
570                 { maxissueqty => $maxissueqty, onshelfholds => $onshelfholds }
571               );
572         }
573
574 #Allows for the 'All' option to work when selecting all patron categories for a circulation rule to apply to.
575         elsif ( $bor eq "*" ) {
576
577             my $search_default_rules =
578               $schema->resultset('DefaultCircRule')->count();
579             my $insert_default_rules = $schema->resultset('Issuingrule')
580               ->new( { maxissueqty => $maxissueqty } );
581         }
582
583 #Allows for the 'All' option to work when selecting all itemtypes for a circulation rule to apply to
584         elsif ( $itemtype eq "*" ) {
585             my $search_default_rules =
586               $schema->resultset('DefaultCircRule')->search(
587                 {},
588                 {
589                     branchcode => $branch
590                 }
591
592               );
593
594             my $insert_default_rules = $schema->resultset('Issuingrule')
595               ->new( { branchcode => $branch, onshelfholds => $onshelfholds } );
596         }
597
598         my $issuingrule = Koha::IssuingRules->find(
599             { categorycode => $bor, itemtype => $itemtype, branchcode => $br }
600         );
601         if ($issuingrule) {
602             $issuingrule->set($params)->store();
603             push @messages,
604               {
605                 type => 'error',
606                 code => 'error_on_insert'
607               }; #Stops crash of the onboarding tool if someone makes a circulation rule with the same item type, library and patron categroy as an exisiting circulation rule.
608
609         }
610         else {
611             Koha::IssuingRule->new()->set($params)->store();
612         }
613     }
614 }
615
616 output_html_with_http_headers $input, $cookie, $template->output;