From 25ba879eca6c8491870e06bb7fd659bbbad41d92 Mon Sep 17 00:00:00 2001 From: Alex Buckley Date: Wed, 21 Dec 2016 00:37:02 +0000 Subject: [PATCH] Bug 17855 - Implemented a minimum and maximum card number allowed for the create patron screen of the onboarding tool. Test plan: 1. Go through the web installer and onboarding tool as outlined here: https://koha-community.org/manual/installation/html/ 2. Notice on the first create patron screen you cannot enter a value lower than 1 for the card number 3.Check the database and you should see that the library, patron category, patron (with superlibrarian permissions), item type and circulation rule are all being successfully inserted into the database. Bug 17855 - Made card number required for the create patron screen to be submitted. Test plan: 1. Go through the web installer and onboarding tool as outlined here: https://koha-community.org/manual/installation/html/ 2. Notice that you must enter a card number to submit the first create patron screen 3. Check the database to see that the library, patron category, patron, item type and circulation rule are all successfully inserting into the datbase. Bug 17855 - Circulation rule is now inserting into the database successfully. Therefore all 5 steps of the onboarding tool (creating a library, patron category, patron, item type and circulation rule) are successfully inserting into the database. Test plan: 1. Go through the web installer and onboarding tool as outlined in the below link: https://koha-community.org/manual/installation/html/ 2. Check the database to see that the library, patron category, patron, item type and circulation rule are all inserting correctly. 3. Notice there are no html regexes implemented on text input fields yet of the onboarding tool. Made card number required Added max and min length for card number --- installer/onboarding.pl | 213 +++++++++++++-------- .../prog/en/modules/onboarding/onboardingstep2.tt | 170 ++++++++++++++++ .../prog/en/modules/onboarding/onboardingstep3.tt | 2 +- .../prog/en/modules/onboarding/onboardingstep5.tt | 12 +- 4 files changed, 310 insertions(+), 87 deletions(-) diff --git a/installer/onboarding.pl b/installer/onboarding.pl index d5574d7..0024db5 100755 --- a/installer/onboarding.pl +++ b/installer/onboarding.pl @@ -40,6 +40,12 @@ use Koha::Patron::HouseboundRoles; use Koha::Token; use Email::Valid; use Module::Load; +use Koha::IssuingRule; +use Koha::IssuingRules; + + + + #Setting variables my $input = new CGI; @@ -187,51 +193,52 @@ if ( $start && $start eq 'Start setting up my Koha' ){ #Once the user submits the page, this code validates the input and adds it #to the database as a new patron category -#} elsif ( $op eq 'add_validate' ) { - my $categorycode = $input->param('categorycode'); - my $description = $input->param('description'); - my $overduenoticerequired = $input->param('overduenoticerequired'); - my $category_type = $input->param('category_type'); - my $default_privacy = $input->param('default_privacy'); - my $enrolmentperiod = $input->param('enrolmentperiod'); - my $enrolmentperioddate = $input->param('enrolmentperioddate') || undef; - - #Converts the string into a date format - if ( $enrolmentperioddate) { - $enrolmentperioddate = output_pref( - { - dt => dt_from_string($enrolmentperioddate), - dateformat => 'iso', - dateonly => 1, - } - ); - } - #Adds to the database - $category = Koha::Patron::Category->new({ - categorycode=> $categorycode, - description => $description, - overduenoticerequired => $overduenoticerequired, - category_type=> $category_type, - default_privacy => $default_privacy, - enrolmentperiod => $enrolmentperiod, - enrolmentperioddate => $enrolmentperioddate, - }); - eval { - $category->store; - }; + my $categorycode = $input->param('categorycode'); + my $description = $input->param('description'); + my $overduenoticerequired = $input->param('overduenoticerequired'); + my $category_type = $input->param('category_type'); + my $default_privacy = $input->param('default_privacy'); + my $enrolmentperiod = $input->param('enrolmentperiod'); + my $enrolmentperioddate = $input->param('enrolmentperioddate') || undef; + + #Converts the string into a date format + if ( $enrolmentperioddate) { + $enrolmentperioddate = output_pref( + { + dt => dt_from_string($enrolmentperioddate), + dateformat => 'iso', + dateonly => 1, + } + ); + } - #Error messages - if($category){ - $message = 'success_on_insert'; - }else{ - $message = 'error_on_insert'; - } + #Adds to the database + $category = Koha::Patron::Category->new({ + categorycode=> $categorycode, + description => $description, + overduenoticerequired => $overduenoticerequired, + category_type=> $category_type, + default_privacy => $default_privacy, + enrolmentperiod => $enrolmentperiod, + enrolmentperioddate => $enrolmentperioddate, + }); + eval { + $category->store; + }; + + #Error messages + if($category){ + $message = 'success_on_insert'; + }else{ + $message = 'error_on_insert'; + } - $template->param('message' => $message); + $template->param('message' => $message); #Create a patron }elsif ( $step && $step == 3 ){ + my $libraries = Koha::Libraries->search( {}, { order_by => ['branchcode'] }, ); $template->param(libraries => $libraries, group_types => [ @@ -250,11 +257,13 @@ if ( $start && $start eq 'Start setting up my Koha' ){ categories => $categories, ); + my $input = new CGI; my $op = $input->param('op') // 'list'; my @messages; my @errors; + my $nok = $input->param('nok'); my ($template, $loggedinuser, $cookie)= get_template_and_user({ template_name => "/onboarding/onboardingstep3.tt", @@ -266,7 +275,7 @@ if ( $start && $start eq 'Start setting up my Koha' ){ }); if($op eq 'add_validate'){ - my %newdata; + my %newdata; #Store the template form values in the newdata hash $newdata{borrowernumber} = $input->param('borrowernumber'); @@ -281,14 +290,14 @@ if ( $start && $start eq 'Start setting up my Koha' ){ $newdata{dateexpiry} = '12/10/2016'; $newdata{privacy} = "default"; - if(my $error_code = checkcardnumber($newdata{cardnumber},$newdata{borrowernumber})){ + $newdata{'cardnumber'} = undef if $newdata{'cardnumber'} =~ /^\s*$/; + if(my $error_code = checkcardnumber($newdata{cardnumber},$newdata{borrowernumber})){ push @errors, $error_code == 1 ? 'ERROR_cardnumber_already_exists' - :$error_code == 2 + :$error_code == 2 ? 'ERROR_cardnumber_length' :() - } - + } #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 @@ -299,6 +308,7 @@ if ( $start && $start eq 'Start setting up my Koha' ){ $member2{'borrowernumber'}=$borrowernumber; my $flag = $input->param('flag'); + if ($input->param('newflags')) { my $dbh=C4::Context->dbh(); my @perms = $input->multi_param('flag'); @@ -314,28 +324,27 @@ if ( $start && $start eq 'Start setting up my Koha' ){ } - # construct flags - my $module_flags = 0; - my $sth=$dbh->prepare("SELECT bit,flag FROM userflags ORDER BY bit"); - $sth->execute(); - while (my ($bit, $flag) = $sth->fetchrow_array) { - if (exists $all_module_perms{$flag}) { + # construct flags + my $module_flags = 0; + my $sth=$dbh->prepare("SELECT bit,flag FROM userflags ORDER BY bit"); + $sth->execute(); + while (my ($bit, $flag) = $sth->fetchrow_array) { + if (exists $all_module_perms{$flag}) { $module_flags += 2**$bit; - } - } - - $sth = $dbh->prepare("UPDATE borrowers SET flags=? WHERE borrowernumber=?"); - $sth->execute($module_flags, $borrowernumber); - - - #Error handling checking if the patron was created successfully - if(!$borrowernumber){ - push @messages, {type=> 'error', code => 'error_on_insert'}; - }else{ - push @messages, {type=> 'message', code => 'success_on_insert'}; - } - } - } + } + } + + $sth = $dbh->prepare("UPDATE borrowers SET flags=? WHERE borrowernumber=?"); + $sth->execute($module_flags, $borrowernumber); + + #Error handling checking if the patron was created successfully + if(!$borrowernumber){ + push @messages, {type=> 'error', code => 'error_on_insert'}; + }else{ + push @messages, {type=> 'message', code => 'success_on_insert'}; + } + } + } }elsif ( $step && $step == 4){ my $createitemtype = $input->param('createitemtype'); $template->param('createitemtype'=> $createitemtype ); @@ -363,14 +372,14 @@ if ( $start && $start eq 'Start setting up my Koha' ){ my $description = $input->param('description'); #store the input from the form - only 2 fields - my $thisitemtype= Koha::ItemType->new( + $itemtype= Koha::ItemType->new( { itemtype => $itemtype_code, description => $description, } ); - eval{ $thisitemtype->store; }; + eval{ $itemtype->store; }; #Error messages - if($thisitemtype){ + if($itemtype){ $message = 'success_on_insert'; }else{ $message = 'error_on_insert'; @@ -378,10 +387,11 @@ if ( $start && $start eq 'Start setting up my Koha' ){ $template->param('message' => $message); } -}elsif ( $step && $step == 5){ - my $test="a"; - warn $test; + + + +}elsif ( $step && $step == 5){ #Fetching all the existing categories to display in a drop down box my $categories; $categories= Koha::Patron::Categories->search(); @@ -395,48 +405,81 @@ if ( $start && $start eq 'Start setting up my Koha' ){ itemtypes => $itemtypes, ); + my $libraries = Koha::Libraries->search( {}, { order_by => ['branchcode'] }, ); + $template->param(libraries => $libraries, + group_types => [ + { categorytype => 'searchdomain', + categories => [ Koha::LibraryCategories->search( { categorytype => 'searchdomain' } ) ], + }, + { categorytype => 'properties', + categories => [ Koha::LibraryCategories->search( { categorytype => 'properties' } ) ], + }, + ] + ); + my $input = CGI->new; - my($template, $loggedinuser, $cookie) =get_template_and_user({ - template_name => "/onboarding/onboardingstep5.tt", - query => $input, - type => "intranet", - authnotrequired=>0, - flagsrequired=> {parameters => 'manage_circ_rules'}, - debug =>1, - }); + my $dbh = C4::Context->dbh; + + my ($template, $loggedinuser, $cookie) + = get_template_and_user({template_name => "/onboarding/onboardingstep5.tt", + query => $input, + type => "intranet", + authnotrequired => 0, + flagsrequired => {parameters => 'manage_circ_rules'}, + debug => 1, + }); - my $type = $input->param('type'); my $branch = $input->param('branch'); + unless ( $branch ) { + if ( C4::Context->preference('DefaultToLoggedInLibraryCircRules') ) { + $branch = Koha::Libraries->search->count() == 1 ? undef : C4::Context::mybranch(); + } + else { + $branch = C4::Context::only_my_library() ? ( C4::Context::mybranch() || '*' ) : '*'; + } + } + $branch = '*' if $branch eq 'NO_LIBRARY_SET'; + my $op = $input->param('op') || q{}; if($op eq 'add_validate'){ + + my $type = $input->param('type'); + my $br = $branch; my $bor = $input->param('categorycode'); my $itemtype = $input->param('itemtype'); my $maxissueqty = $input->param('maxissueqty'); my $issuelength = $input->param('issuelength'); - #$issuelength = $issuelength eq q{} ? undef : $issuelength; my $lengthunit = $input->param('lengthunit'); my $renewalsallowed = $input->param('renewalsallowed'); my $renewalperiod = $input->param('renewalperiod'); - my $onshelfholds = $input->param('onshelfholds'); + my $onshelfholds = $input->param('onshelfholds') || 0; + $maxissueqty =~ s/\s//g; + $maxissueqty = undef if $maxissueqty !~ /^\d+/; + $issuelength = $issuelength eq q{} ? undef : $issuelength; my $params ={ + branchcode => $br, categorycode => $bor, itemtype => $itemtype, maxissueqty => $maxissueqty, renewalsallowed => $renewalsallowed, renewalperiod => $renewalperiod, + issuelength => $issuelength, lengthunit => $lengthunit, onshelfholds => $onshelfholds, }; - my $issuingrule = Koha::IssuingRules->find({categorycode => $bor, itemtype => $itemtype}); + + my @messages; + + my $issuingrule = Koha::IssuingRules->find({categorycode => $bor, itemtype => $itemtype, branchcode => $br }); if($issuingrule){ $issuingrule->set($params)->store(); + push @messages, {type=> 'error', code => 'error_on_insert'};#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. }else{ Koha::IssuingRule->new()->set($params)->store(); } } - } - +} output_html_with_http_headers $input, $cookie, $template->output; diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/onboarding/onboardingstep2.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/onboarding/onboardingstep2.tt index 1635c68..f3a8276 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/onboarding/onboardingstep2.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/onboarding/onboardingstep2.tt @@ -30,6 +30,172 @@ jQuery.validator.addMethod( "enrollment_period", function(){ } }, MSG_ONE_ENROLLMENTPERIOD); +//Testing the jquery + + + + +var debug = ""; +var dformat = "us"; +var sentmsg = 0; +if (debug > 1) {alert("dateformat: " + dformat + "\ndebug is on (level " + debug + ")");} +var MSG_PLEASE_ENTER_A_VALID_DATE = (_("Please enter a valid date (should match %s).")); + +function is_valid_date(date) { + // An empty string is considered as a valid date for convenient reasons. + if ( date === '' ) return 1; + var dateformat = dateformat_str = 'us'; + if ( dateformat == 'us' ) { + if ( date.search(/^\d{2}\/\d{2}\/\d{4}($|\s)/) == -1 ) return 0; + dateformat = 'mm/dd/yy'; + } else if ( dateformat == 'metric' ) { + if ( date.search(/^\d{2}\/\d{2}\/\d{4}($|\s)/) == -1 ) return 0; + dateformat = 'dd/mm/yy'; + } else if (dateformat == 'iso' ) { + if ( date.search(/^\d{4}-\d{2}-\d{2}($|\s)/) == -1 ) return 0; + dateformat = 'yy-mm-dd'; + } else if ( dateformat == 'dmydot' ) { + if ( date.search(/^\d{2}\.\d{2}\.\d{4}($|\s)/) == -1 ) return 0; + dateformat = 'dd.mm.yy'; + } + try { + $.datepicker.parseDate(dateformat, date); + } catch (e) { + return 0; + }; + return 1; +} + +function get_dateformat_str(dateformat) { + var dateformat_str; + if ( dateformat == 'us' ) { + dateformat_str = 'mm/dd/yyyy'; + } else if ( dateformat == 'metric' ) { + dateformat_str = 'dd/mm/yyyy'; + } else if (dateformat == 'iso' ) { + dateformat_str = 'yyyy-mm-dd'; + } else if ( dateformat == 'dmydot' ) { + dateformat_str = 'dd.mm.yyyy'; + } + return dateformat_str; +} + +function validate_date (dateText, inst) { + if ( !is_valid_date(dateText) ) { + var dateformat_str = get_dateformat_str( 'us' ); + alert(MSG_PLEASE_ENTER_A_VALID_DATE.format(dateformat_str)); + $('#'+inst.id).val(''); + } +} + +function Date_from_syspref(dstring) { + var dateX = dstring.split(/[-/.]/); + if (debug > 1 && sentmsg < 1) {sentmsg++; alert("Date_from_syspref(" + dstring + ") splits to:\n" + dateX.join("\n"));} + if (dformat === "iso") { + return new Date(dateX[0], (dateX[1] - 1), dateX[2]); // YYYY-MM-DD to (YYYY,m(0-11),d) + } else if (dformat === "us") { + return new Date(dateX[2], (dateX[0] - 1), dateX[1]); // MM/DD/YYYY to (YYYY,m(0-11),d) + } else if (dformat === "metric") { + return new Date(dateX[2], (dateX[1] - 1), dateX[0]); // DD/MM/YYYY to (YYYY,m(0-11),d) + } else if (dformat === "dmydot") { + return new Date(dateX[2], (dateX[1] - 1), dateX[0]); // DD.MM.YYYY to (YYYY,m(0-11),d) + } else { + if (debug > 0) {alert("KOHA ERROR - Unrecognized date format: " +dformat);} + return 0; + } +} + +function DateTime_from_syspref(date_time) { + var parts = date_time.split(" "); + var date = parts[0]; + var time = parts[1]; + parts = time.split(":"); + var hour = parts[0]; + var minute = parts[1]; + if ( hour < 0 || hour > 23 ) { + return 0; + } + if ( minute < 0 || minute > 59 ) { + return 0; + } + var datetime = Date_from_syspref( date ); + if ( isNaN( datetime.getTime() ) ) { + return 0; + } + datetime.setHours( hour ); + datetime.setMinutes( minute ); + return datetime; +} + + +/* Instead of including multiple localization files as you would normally see with + jQueryUI we expose the localization strings in the default configuration */ +jQuery(function($){ + $.datepicker.regional[''] = { + closeText: _("Done"), + prevText: _("Prev"), + nextText: _("Next"), + currentText: _("Today"), + monthNames: [_("January"),_("February"),_("March"),_("April"),_("May"),_("June"), + _("July"),_("August"),_("September"),_("October"),_("November"),_("December")], + monthNamesShort: [_("Jan"), _("Feb"), _("Mar"), _("Apr"), _("May"), _("Jun"), + _("Jul"), _("Aug"), _("Sep"), _("Oct"), _("Nov"), _("Dec")], + dayNames: [_("Sunday"), _("Monday"), _("Tuesday"), _("Wednesday"), _("Thursday"), _("Friday"), _("Saturday")], + dayNamesShort: [_("Sun"), _("Mon"), _("Tue"), _("Wed"), _("Thu"), _("Fri"), _("Sat")], + dayNamesMin: [_("Su"),_("Mo"),_("Tu"),_("We"),_("Th"),_("Fr"),_("Sa")], + weekHeader: _("Wk"), + dateFormat: "mm/dd/yy", + firstDay: 0, + isRTL: false, + showMonthAfterYear: false, + yearSuffix: ''}; + $.datepicker.setDefaults($.datepicker.regional['']); +}); + +$(document).ready(function(){ + + $.datepicker.setDefaults({ + showOn: "both", + changeMonth: true, + changeYear: true, + buttonImage: '/intranet-tmpl/prog/img/famfamfam/silk/calendar.png', + buttonImageOnly: true, + showButtonPanel: true, + showOtherMonths: true, + selectOtherMonths: true + }); + $( ".datepicker" ).datepicker({ + onClose: function(dateText, inst) { + validate_date(dateText, inst); + }, + }).on("change", function(e, value) { + if ( ! is_valid_date( $(this).val() ) ) {$(this).val("");} + }); + // http://jqueryui.com/demos/datepicker/#date-range + var dates = $( ".datepickerfrom, .datepickerto" ).datepicker({ + changeMonth: true, + numberOfMonths: 1, + onSelect: function( selectedDate ) { + var option = this.id == "from" ? "minDate" : "maxDate", + instance = $( this ).data( "datepicker" ); + date = $.datepicker.parseDate( + instance.settings.dateFormat || + $.datepicker._defaults.dateFormat, + selectedDate, instance.settings ); + dates.not( this ).datepicker( "option", option, date ); + }, + onClose: function(dateText, inst) { + validate_date(dateText, inst); + }, + }).on("change", function(e, value) { + if ( ! is_valid_date( $(this).val() ) ) {$(this).val("");} + }); +}); + + + + + $(document).ready(function(){ $("#category_form").validate({ rules: { @@ -209,6 +375,10 @@ $(document).ready(function(){
  • + ... + + +
  • diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/onboarding/onboardingstep3.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/onboarding/onboardingstep3.tt index 83667cb..8191801 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/onboarding/onboardingstep3.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/onboarding/onboardingstep3.tt @@ -68,7 +68,7 @@
    1. - + Required
    2. diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/onboarding/onboardingstep5.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/onboarding/onboardingstep5.tt index f2a7ac8..c00c7ca 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/onboarding/onboardingstep5.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/onboarding/onboardingstep5.tt @@ -47,7 +47,7 @@ [% ELSE %] -

      Create a new Circulation rule

      +

      Create a new Circulation rule

      @@ -55,6 +55,16 @@
      1. + + + Required +
      2. +