From 4b92258f6e9240c4b53fe80ff56dfdcfb534c234 Mon Sep 17 00:00:00 2001 From: Thibaud Guillot Date: Wed, 2 Feb 2022 17:02:15 +0100 Subject: [PATCH] Bug 18064: Add syspref to launch longOverdue script with calendar support The problem here is that the longOverdue script does not support calendars and when libraries set their holidays, long overdues do not take this into account. For example, during the covid pandemic, some libraries were closed for days, maybe months, but longOverdue didn't care and set "lost" or other values on the items. This fix / enhancement based on taking calendars into account to test it, regardless of your rules related to longOverdue, I propose this test plan: Test plan : 1) For clearer vision on what the patch does, have at least "2" libraries 2) Go to Tools/Calendar and place holidays, on each of the libraries for example, of any kind (special, repeated, as you want) 3) Manually run the misc/cronjobs/longoverdue.pl script with the -v (verbose) argument to get as much information as possible 4) You will see a common "block", with today's date + 366 days (by default if you don't pass any arguments to the script), holidays are not taken into account in this date range 5) Apply my patch 6) Launch the updatedatabase 7) Set the new system preference "LongOverdueNoticeCalendar" to "use calendar" 8) Repeat step 3 9) You will see in output one line per library and according to the number of days off in the interval of dates, the start date of the analysis will have been postponed by as many days in order to take these holidays into account. If something is not completely clear, we can of course discuss it --- ...4-add_LongOverdueNoticeCalendar_syspref.pl | 15 +++++ installer/data/mysql/mandatory/sysprefs.sql | 1 + .../admin/preferences/circulation.pref | 6 ++ misc/cronjobs/longoverdue.pl | 66 +++++++++++++++++-- 4 files changed, 83 insertions(+), 5 deletions(-) create mode 100755 installer/data/mysql/atomicupdate/bug_18064-add_LongOverdueNoticeCalendar_syspref.pl diff --git a/installer/data/mysql/atomicupdate/bug_18064-add_LongOverdueNoticeCalendar_syspref.pl b/installer/data/mysql/atomicupdate/bug_18064-add_LongOverdueNoticeCalendar_syspref.pl new file mode 100755 index 00000000000..807a723afb4 --- /dev/null +++ b/installer/data/mysql/atomicupdate/bug_18064-add_LongOverdueNoticeCalendar_syspref.pl @@ -0,0 +1,15 @@ +use Modern::Perl; + +return { + bug_number => "BUG_18064", + description => "Add new system preference LongOverdueNoticeCalendar", + up => sub { + my ($args) = @_; + my ( $dbh, $out ) = @$args{qw(dbh out)}; + + $dbh->do( + q{INSERT IGNORE INTO systempreferences (variable,value,options,explanation,type) VALUES ('LongOverdueNoticeCalendar', '0', NULL, 'Take the calendar into consideration when generating long overdue notices', 'Yes/No') } + ); + say $out "Added new system preference 'LongOverdueNoticeCalendar'"; + }, +}; diff --git a/installer/data/mysql/mandatory/sysprefs.sql b/installer/data/mysql/mandatory/sysprefs.sql index b58114d802e..6d0e5533433 100644 --- a/installer/data/mysql/mandatory/sysprefs.sql +++ b/installer/data/mysql/mandatory/sysprefs.sql @@ -373,6 +373,7 @@ INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` ('LocalHoldsPriorityItemControl', 'holdingbranch', 'holdingbranch|homebranch', 'decides if the feature operates using the item''s home or holding library.', 'Choice'), ('LocalHoldsPriorityPatronControl', 'PickupLibrary', 'HomeLibrary|PickupLibrary', 'decides if the feature operates using the library set as the patron''s home library, or the library set as the pickup library for the given hold.', 'Choice'), ('LockExpiredDelay','','','Delay for locking expired patrons (empty means no locking)','Integer'), +('LongOverdueNoticeCalendar',0,NULL,'Take the calendar into consideration when generating long overdue notices','YesNo'), ('makePreviousSerialAvailable','0','','make previous serial automatically available when collecting a new serial. Please note that the item-level_itypes syspref must be set to specific item.','YesNo'), ('Mana','2',NULL,'request to Mana Webservice. Mana centralize common information between other Koha to facilitate the creation of new subscriptions, vendors, report queries etc... You can search, share, import and comment the content of Mana.','Choice'), ('MARCAuthorityControlField008','|| aca||aabn | a|a d',NULL,'Define the contents of MARC21 authority control field 008 position 06-39','Textarea'), diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref index 40f2d65a81e..3cc63920f90 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref @@ -384,6 +384,12 @@ Circulation: - "Send all notices as a BCC to this email address:" - pref: NoticeBcc class: email + - + - pref: LongOverdueNoticeCalendar + choices: + 1: Use calendar + 0: Ignore calendar + - "when working out the period for long overdue notices." - - pref: OverdueNoticeCalendar choices: diff --git a/misc/cronjobs/longoverdue.pl b/misc/cronjobs/longoverdue.pl index 2d313b77b24..6365db085be 100755 --- a/misc/cronjobs/longoverdue.pl +++ b/misc/cronjobs/longoverdue.pl @@ -30,6 +30,8 @@ use warnings; use Getopt::Long qw( GetOptions ); use Pod::Usage qw( pod2usage ); +use DateTime; +use DateTime::Duration; use C4::Circulation qw( LostItem MarkIssueReturned ); use C4::Context; @@ -38,6 +40,9 @@ use Koha::ItemTypes; use Koha::Patron::Categories; use Koha::Patrons; use Koha::Script -cron; +use Koha::Calendar; +use Koha::DateUtils qw( dt_from_string ); + my $lost; # key=lost value, value=num days. my ($charge, $verbose, $confirm, $quiet); @@ -314,6 +319,37 @@ sub longoverdue_sth { return C4::Context->dbh->prepare($query); } +sub get_number_of_holidays { + my ( $start_date, $end_date ) = @_; + + my @holidays_by_branch; + + $start_date = dt_from_string($start_date); + $end_date = dt_from_string($end_date); + + my @branches = Koha::Libraries->search( {}, { order_by => ['branchcode'] } )->as_list; + my $calendar; + + foreach my $branch (@branches) { + my $date_to_run = $start_date->clone(); + my $branchcode = $branch->branchcode; + my $i = 0; + + $calendar = Koha::Calendar->new( branchcode => $branchcode ); + + while ( $date_to_run ne $end_date ) { + + # printf "\n Treatment of the day : %s \n", $date_to_run; + if ( $calendar->is_holiday($date_to_run) ) { + $i++; + } + $date_to_run->add( days => 1 ); + } + push @holidays_by_branch, { 'branchcode' => $branchcode, 'nb_holidays' => $i }; + } + return @holidays_by_branch; +} + my $dbh = C4::Context->dbh; my @available_categories = Koha::Patron::Categories->search()->get_column('categorycode'); @@ -386,11 +422,30 @@ foreach my $startrange (sort keys %$lost) { if( my $lostvalue = $lost->{$startrange} ) { my ($date1) = bounds($startrange); my ($date2) = bounds( $endrange); - # print "\nRange ", ++$i, "\nDue $startrange - $endrange days ago ($date2 to $date1), lost => $lostvalue\n" if($verbose); - $verbose and - printf "\nRange %s\nDue %3s - %3s days ago (%s to %s), lost => %s\n", ++$i, - $startrange, $endrange, $date2, $date1, $lostvalue; - $sth_items->execute($startrange, $endrange, $lostvalue); + + if ( C4::Context->preference('LongOverdueNoticeCalendar') ) { + my @holidays_by_branch = get_number_of_holidays( $date2, $date1 ); + + foreach my $branch (@holidays_by_branch) { + + my $date2_with_holidays = dt_from_string($date2)->subtract( days => $branch->{'nb_holidays'} )->ymd; + my $endrange_with_holidays = $endrange + $branch->{'nb_holidays'}; + + $verbose + and printf "\nBranchcode %s\nDue %3s - %3s days ago (%s to %s) - with %s holiday(s), lost => %s\n", + $branch->{'branchcode'}, + $startrange, $endrange_with_holidays, $date2_with_holidays, $date1, $branch->{'nb_holidays'}, + $lostvalue; + $sth_items->execute( $startrange, $endrange_with_holidays, $lostvalue ); + } + } else { + # print "\nRange ", ++$i, "\nDue $startrange - $endrange days ago ($date2 to $date1), lost => $lostvalue\n" if($verbose); + $verbose + and printf "\nRange %s\nDue %3s - %3s days ago (%s to %s), lost => %s\n", ++$i, + $startrange, $endrange, $date2, $date1, $lostvalue; + $sth_items->execute( $startrange, $endrange, $lostvalue ); + } + $count=0; ITEM: while (my $row=$sth_items->fetchrow_hashref) { if( $filter_borrower_categories ) { @@ -414,6 +469,7 @@ foreach my $startrange (sort keys %$lost) { } $count++; } + push @report, { startrange => $startrange, endrange => $endrange, -- 2.30.2