Bug 17855: Redirect to the installer if installation process is not done yet
[koha.git] / installer / onboarding.pl
blob943def71babcc78a051220e7174d7083b2259804
1 #!/usr/bin/perl
3 # This file is part of Koha.
5 # Copyright (C) 2017 Catalyst IT
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.
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.
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>.
20 use Modern::Perl;
21 use C4::Context;
22 use C4::InstallAuth;
23 use CGI qw ( -utf8 );
24 use C4::Output;
25 use C4::Members;
26 use Koha::Patrons;
27 use Koha::Libraries;
28 use Koha::Database;
29 use Koha::DateUtils;
30 use Koha::Patron::Categories;
31 use Koha::Patron::Category;
32 use Koha::ItemTypes;
33 use Koha::IssuingRule;
34 use Koha::IssuingRules;
36 #Setting variables
37 my $input = new CGI;
38 my $step = $input->param('step');
40 unless ( C4::Context->preference('Version') ) {
41 print $input->redirect("/cgi-bin/koha/installer/install.pl");
42 exit;
45 #Getting the appropriate template to display to the user
46 my ( $template, $loggedinuser, $cookie ) =
47 C4::InstallAuth::get_template_and_user(
49 template_name => "/onboarding/onboardingstep"
50 . ( $step ? $step : 1 ) . ".tt",
51 query => $input,
52 type => "intranet",
53 authnotrequired => 0,
54 debug => 1,
58 #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.
59 my $op = $input->param('op') || '';
60 $template->param( 'op' => $op );
62 my $schema = Koha::Database->new()->schema();
64 if ( $op && $op eq 'finish' )
65 { #If the value of $op equals 'finish' then redirect user to /cgi-bin/koha/mainpage.pl
66 print $input->redirect("/cgi-bin/koha/mainpage.pl");
67 exit;
70 my $libraries = Koha::Libraries->search( {}, { order_by => ['branchcode'] }, );
71 $template->param(
72 libraries => $libraries,
73 group_types => [
75 categorytype => 'searchdomain',
76 categories => [
77 Koha::LibraryCategories->search(
78 { categorytype => 'searchdomain' }
83 categorytype => 'properties',
84 categories => [
85 Koha::LibraryCategories->search(
86 { categorytype => 'properties' }
93 #Select all the patron category records in the categories database table and give them to the template
94 my $categories = Koha::Patron::Categories->search();
95 $template->param( 'categories' => $categories, );
97 #Check if the $step variable equals 1 i.e. the user has clicked to create a library in the create library screen 1
98 my $itemtypes = Koha::ItemTypes->search();
99 $template->param( 'itemtypes' => $itemtypes, );
101 if ( $step && $step == 1 ) {
103 #store inputted parameters in variables
104 my $branchcode = $input->param('branchcode');
105 $branchcode = uc($branchcode);
106 my $categorycode = $input->param('categorycode');
107 my $op = $input->param('op') || 'list';
108 my $message;
109 my $library;
111 #Take the text 'branchname' and store it in the @fields array
112 my @fields = qw(
113 branchname
116 $template->param( 'branchcode' => $branchcode );
117 $branchcode =~ s|\s||g
118 ; # Use a regular expression to check the value of the inputted branchcode
120 #Create a new library object and store the branchcode and @fields array values in this new library object
121 $library = Koha::Library->new(
123 branchcode => $branchcode,
124 ( map { $_ => scalar $input->param($_) || undef } @fields )
128 eval { $library->store; }; #Use the eval{} function to store the library object
129 if ($library) {
130 $message = 'success_on_insert';
132 else {
133 $message = 'error_on_insert';
135 $template->param( 'message' => $message );
137 #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
139 elsif ( $step && $step == 2 ) {
140 if ( $op eq "add_validate_category" ) {
142 #Initialising values
143 my $searchfield = $input->param('description') // q||;
144 my $categorycode = $input->param('categorycode');
145 my $op = $input->param('op') // 'list';
146 my $message;
147 my $category;
148 $template->param( 'categorycode' => $categorycode );
150 my ( $template, $loggedinuser, $cookie ) =
151 C4::InstallAuth::get_template_and_user(
153 template_name => "/onboarding/onboardingstep2.tt",
154 query => $input,
155 type => "intranet",
156 authnotrequired => 0,
157 flagsrequired =>
158 { parameters => 'parameters_remaining_permissions' },
159 debug => 1,
163 #Once the user submits the page, this code validates the input and adds it
164 #to the database as a new patron category
165 $categorycode = $input->param('categorycode');
166 my $description = $input->param('description');
167 my $overduenoticerequired = $input->param('overduenoticerequired');
168 my $category_type = $input->param('category_type');
169 my $default_privacy = $input->param('default_privacy');
170 my $enrolmentperiod = $input->param('enrolmentperiod');
171 my $enrolmentperioddate = $input->param('enrolmentperioddate') || undef;
173 #Converts the string into a date format
174 if ($enrolmentperioddate) {
175 $enrolmentperioddate = output_pref(
177 dt => dt_from_string($enrolmentperioddate),
178 dateformat => 'DateTime',
179 dateonly => 1,
184 #Adds a new patron category to the database
185 $category = Koha::Patron::Category->new(
187 categorycode => $categorycode,
188 description => $description,
189 overduenoticerequired => $overduenoticerequired,
190 category_type => $category_type,
191 default_privacy => $default_privacy,
192 enrolmentperiod => $enrolmentperiod,
193 enrolmentperioddate => $enrolmentperioddate
197 eval { $category->store; };
199 #Error messages
200 if ($category) {
201 $message = 'success_on_insert';
203 else {
204 $message = 'error_on_insert';
207 $template->param( 'message' => $message );
210 #Create a patron
212 elsif ( $step && $step == 3 ) {
213 my $firstpassword = $input->param('password') || '';
214 my $secondpassword = $input->param('password2') || '';
216 #Find all patron records in the database and hand them to the template
217 my %currentpatrons = Koha::Patrons->search();
218 my $currentpatrons = values %currentpatrons;
219 $template->param( 'patrons' => $currentpatrons );
221 #Find all library records in the database and hand them to the template to display in the library dropdown box
222 my $libraries =
223 Koha::Libraries->search( {}, { order_by => ['branchcode'] }, );
224 $template->param(
225 libraries => $libraries,
226 group_types => [
228 categorytype => 'searchdomain',
229 categories => [
230 Koha::LibraryCategories->search(
231 { categorytype => 'searchdomain' }
236 categorytype => 'properties',
237 categories => [
238 Koha::LibraryCategories->search(
239 { categorytype => 'properties' }
246 #Find all patron categories in the database and hand them to the template to display in the patron category dropdown box
247 my $categories = Koha::Patron::Categories->search();
248 $template->param( 'categories' => $categories, );
250 #Incrementing the highest existing patron cardnumber to prevent duplicate cardnumber entry
252 my $existing_cardnumber =
253 $schema->resultset('Borrower')->get_column('cardnumber')->max() // 0;
255 my $new_cardnumber = $existing_cardnumber + 1;
256 $template->param( "newcardnumber" => $new_cardnumber );
258 my $op = $input->param('op') // 'list';
259 my $minpw = C4::Context->preference("minPasswordLength");
260 $template->param( "minPasswordLength" => $minpw );
261 my @messages;
262 my @errors;
263 my $nok = $input->param('nok');
264 my $cardnumber = $input->param('cardnumber');
265 my $borrowernumber = $input->param('borrowernumber');
266 my $userid = $input->param('userid');
268 # function to designate mandatory fields (visually with css)
269 my $check_BorrowerMandatoryField =
270 C4::Context->preference("BorrowerMandatoryField");
271 my @field_check = split( /\|/, $check_BorrowerMandatoryField );
272 foreach (@field_check) {
273 $template->param( "mandatory$_" => 1 );
274 $template->param(
275 BorrowerMandatoryField =>
276 C4::Context->preference("BorrowerMandatoryField")
277 , #field to test with javascript
281 #If the entered cardnumber causes an error hand this error to the @errors array
282 if ( my $error_code = checkcardnumber( $cardnumber, $borrowernumber ) ) {
283 push @errors,
284 $error_code == 1 ? 'ERROR_cardnumber_already_exists'
285 : $error_code == 2 ? 'ERROR_cardnumber_length'
286 : ();
289 #If the entered password causes an error hand this error to the @errors array
290 push @errors, "ERROR_password_mismatch"
291 if $firstpassword ne $secondpassword;
292 push @errors, "ERROR_short_password"
293 if ( $firstpassword
294 && $minpw
295 && $firstpassword ne '****'
296 && ( length($firstpassword) < $minpw ) );
298 #Passing errors to template
299 $nok = $nok || scalar(@errors);
301 #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
302 if ($nok) {
303 foreach my $error (@errors) {
304 if ( $error eq 'ERROR_password_mismatch' ) {
305 $template->param( errorpasswordmismatch => 1 );
307 if ( $error eq 'ERROR_login_exist' ) {
308 $template->param( errorloginexists => 1 );
310 if ( $error eq 'ERROR_cardnumber_already_exists' ) {
311 $template->param( errorcardnumberexists => 1 );
313 if ( $error eq 'ERROR_cardnumber_length' ) {
314 $template->param( errorcardnumberlength => 1 );
316 if ( $error eq 'ERROR_short_password' ) {
317 $template->param( errorshortpassword => 1 );
320 $template->param( 'nok' => 1 );
322 #Else if no errors have been caused by the users inputted card number or password then insert the patron into the borrowers table
324 else {
325 my ( $template, $loggedinuser, $cookie ) =
326 C4::InstallAuth::get_template_and_user(
328 template_name => "/onboarding/onboardingstep3.tt",
329 query => $input,
330 type => "intranet",
331 authnotrequired => 0,
332 flagsrequired => { borrowers => 1 },
333 debug => 1,
337 if ( $op eq 'add_validate' ) {
338 my %newdata;
340 #Store the template form values in the newdata hash
341 $newdata{borrowernumber} = $input->param('borrowernumber');
342 $newdata{surname} = $input->param('surname');
343 $newdata{firstname} = $input->param('firstname');
344 $newdata{cardnumber} = $input->param('cardnumber');
345 $newdata{branchcode} = $input->param('libraries');
346 $newdata{categorycode} = $input->param('categorycode_entry');
347 $newdata{userid} = $input->param('userid');
348 $newdata{password} = $input->param('password');
349 $newdata{password2} = $input->param('password2');
350 $newdata{privacy} = "default";
351 $newdata{address} = "";
352 $newdata{city} = "";
354 #Hand tne the dateexpiry of the patron based on the patron category it is created from
355 my $patron_category =
356 Koha::Patron::Categories->find( $newdata{categorycode} );
357 $newdata{dateexpiry} =
358 $patron_category->get_expiry_date( $newdata{dateenrolled} );
360 #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
361 my $borrowernumber = &AddMember(%newdata);
363 #Create a hash named member2 and fill it with the borrowernumber of the borrower that has just been created
364 my %member2;
365 $member2{'borrowernumber'} = $borrowernumber;
367 #Perform data validation on the flag that has been handed to onboarding.pl by the template
368 my $flag = $input->param('flag');
369 if ( $input->param('newflags') ) {
370 my @perms = $input->multi_param('flag');
371 my %all_module_perms = ();
372 my %sub_perms = ();
373 foreach my $perm (@perms) {
374 if ( $perm !~ /:/ ) {
375 $all_module_perms{$perm} = 1;
377 else {
378 my ( $module, $sub_perm ) = split /:/, $perm, 2;
379 push @{ $sub_perms{$module} }, $sub_perm;
383 # construct flags
384 my @userflags = $schema->resultset('Userflag')->search(
387 order_by => { -asc => 'bit' },
391 #Setting superlibrarian permissions for new patron
392 my $flags =
393 Koha::Patrons->find($borrowernumber)->set( { flags => 1 } )
394 ->store;
396 #Error handling checking if the patron was created successfully
397 if ( !$borrowernumber ) {
398 push @messages,
399 { type => 'error', code => 'error_on_insert' };
401 else {
402 push @messages,
403 { type => 'message', code => 'success_on_insert' };
409 elsif ( $step && $step == 4 ) {
410 my ( $template, $borrowernumber, $cookie ) =
411 C4::InstallAuth::get_template_and_user(
413 template_name => "/onboarding/onboardingstep4.tt",
414 query => $input,
415 type => "intranet",
416 authnotrequired => 0,
417 flagsrequired =>
418 { parameters => 'parameters_remaining_permissions' },
419 debug => 1,
422 if ( $op eq "add_validate" ) {
423 my $description = $input->param('description');
424 my $itemtype_code = $input->param('itemtype');
425 $itemtype_code = uc($itemtype_code);
427 #Create a new itemtype object using the user inputted itemtype and description
428 my $itemtype = Koha::ItemType->new(
430 itemtype => $itemtype_code,
431 description => $description,
434 eval { $itemtype->store; };
435 my $message;
437 #Fill the $message variable with an error if the item type object was not successfully created and inserted into the itemtypes table
438 if ($itemtype) {
439 $message = 'success_on_insert';
441 else {
442 $message = 'error_on_insert';
444 $template->param( 'message' => $message );
447 elsif ( $step && $step == 5 ) {
449 #Find all the existing categories to display in a dropdown box in the template
450 my $categories;
451 $categories = Koha::Patron::Categories->search();
452 $template->param( categories => $categories, );
454 #Find all the exisiting item types to display in a dropdown box in the template
455 my $itemtypes;
456 $itemtypes = Koha::ItemTypes->search();
457 $template->param( itemtypes => $itemtypes, );
459 #Find all the exisiting libraries to display in a dropdown box in the template
460 my $libraries =
461 Koha::Libraries->search( {}, { order_by => ['branchcode'] }, );
462 $template->param(
463 libraries => $libraries,
464 group_types => [
466 categorytype => 'searchdomain',
467 categories => [
468 Koha::LibraryCategories->search(
469 { categorytype => 'searchdomain' }
474 categorytype => 'properties',
475 categories => [
476 Koha::LibraryCategories->search(
477 { categorytype => 'properties' }
484 my $input = CGI->new;
486 my ( $template, $loggedinuser, $cookie ) =
487 C4::InstallAuth::get_template_and_user(
489 template_name => "/onboarding/onboardingstep5.tt",
490 query => $input,
491 type => "intranet",
492 authnotrequired => 0,
493 flagsrequired => { parameters => 'manage_circ_rules' },
494 debug => 1,
498 #If no libraries exist then set the $branch value to *
499 my $branch = $input->param('branch');
500 unless ($branch) {
501 if ( C4::Context->preference('DefaultToLoggedInLibraryCircRules') ) {
502 $branch =
503 Koha::Libraries->search->count() == 1
504 ? undef
505 : C4::Context::mybranch();
507 else {
508 $branch =
509 C4::Context::only_my_library()
510 ? ( C4::Context::mybranch() || '*' )
511 : '*';
514 $branch = '*' if $branch eq 'NO_LIBRARY_SET';
515 my $op = $input->param('op') || q{};
517 if ( $op eq 'add_validate' ) {
518 my $type = $input->param('type');
519 my $br = $input->param('branch');
520 my $bor = $input->param('categorycode');
521 my $itemtype = $input->param('itemtype');
522 my $maxissueqty = $input->param('maxissueqty');
523 my $issuelength = $input->param('issuelength');
524 my $lengthunit = $input->param('lengthunit');
525 my $renewalsallowed = $input->param('renewalsallowed');
526 my $renewalperiod = $input->param('renewalperiod');
527 my $onshelfholds = $input->param('onshelfholds') || 0;
528 $maxissueqty =~ s/\s//g;
529 $maxissueqty = undef if $maxissueqty !~ /^\d+/;
530 $issuelength = $issuelength eq q{} ? undef : $issuelength;
532 my $params = {
533 branchcode => $br,
534 categorycode => $bor,
535 itemtype => $itemtype,
536 maxissueqty => $maxissueqty,
537 renewalsallowed => $renewalsallowed,
538 renewalperiod => $renewalperiod,
539 issuelength => $issuelength,
540 lengthunit => $lengthunit,
541 onshelfholds => $onshelfholds,
544 my @messages;
546 #Allows for the 'All' option to work when selecting all libraries for a circulation rule to apply to.
547 if ( $branch eq "*" ) {
548 my $search_default_rules =
549 $schema->resultset('DefaultCircRule')->count();
550 my $insert_default_rules =
551 $schema->resultset('Issuingrule')
552 ->new(
553 { maxissueqty => $maxissueqty, onshelfholds => $onshelfholds }
557 #Allows for the 'All' option to work when selecting all patron categories for a circulation rule to apply to.
558 elsif ( $bor eq "*" ) {
560 my $search_default_rules =
561 $schema->resultset('DefaultCircRule')->count();
562 my $insert_default_rules = $schema->resultset('Issuingrule')
563 ->new( { maxissueqty => $maxissueqty } );
566 #Allows for the 'All' option to work when selecting all itemtypes for a circulation rule to apply to
567 elsif ( $itemtype eq "*" ) {
568 my $search_default_rules =
569 $schema->resultset('DefaultCircRule')->search(
572 branchcode => $branch
577 my $insert_default_rules = $schema->resultset('Issuingrule')
578 ->new( { branchcode => $branch, onshelfholds => $onshelfholds } );
581 my $issuingrule = Koha::IssuingRules->find(
582 { categorycode => $bor, itemtype => $itemtype, branchcode => $br }
584 if ($issuingrule) {
585 $issuingrule->set($params)->store();
586 push @messages,
588 type => 'error',
589 code => 'error_on_insert'
590 }; #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.
593 else {
594 Koha::IssuingRule->new()->set($params)->store();
599 output_html_with_http_headers $input, $cookie, $template->output;