Bugzilla – Attachment 153254 Details for
Bug 6796
Overnight checkouts taking into account opening and closing hours
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 6796: Consider library hours when calculating due date + tests
Bug-6796-Consider-library-hours-when-calculating-d.patch (text/plain), 12.34 KB, created by
Aleisha Amohia
on 2023-07-10 04:29:50 UTC
(
hide
)
Description:
Bug 6796: Consider library hours when calculating due date + tests
Filename:
MIME Type:
Creator:
Aleisha Amohia
Created:
2023-07-10 04:29:50 UTC
Size:
12.34 KB
patch
obsolete
>From f34d1c2999de260ab363519f58763e9fa9441053 Mon Sep 17 00:00:00 2001 >From: Aleisha Amohia <aleishaamohia@hotmail.com> >Date: Wed, 8 Sep 2021 03:59:12 +1200 >Subject: [PATCH] Bug 6796: Consider library hours when calculating due date + > tests > >This feature adds the ability to set opening and closing hours for your >library and for these hours to be considered when calculating due dates >for hourly loans. If the due date for an hourly loan falls after the >library closes, the library can choose for the due date to be shortened >to meet the close time, or extended to meet the open time the next day. >This feature adds a new table 'branch_hours' for storing the open and >close times per day for each library, and a new system preference >'ConsiderLibraryHoursWhenIssuing' to choose which behaviour should be >followed when calculating due dates. > >To test: >1. Apply patches and update database. Upgrade schema if not applying >patch with schema changes. Restart services. >2. Go to Administration -> Libraries. Edit a library and scroll to the >bottom to find the 'opening hours' section. Test adding and removing >open and close times on various days. Confirm saving works as expected. >3. Add a new library and test adding open and close times works as >expected. >4. Edit your default library and save open and close times for each day. >5. Go to Administration -> Circulation and fine rules. Edit a rule, set >the unit to 'hours' and set the loan period to a number that would cause >a checkout to be due after the close time you just set, i.e. if you set >your close time to be 5pm and your system time is currently 1pm, set the >loan period to be 5 (5 hours) so the calculated due date would be 6pm. >6. Go to Administration -> system preferences. Search for >ConsiderLibraryHoursWhenIssuing. It should be under 'Checkout policy' in >the Circulation system preferences. Confirm the pre-selected option is >'ignore'. Keep this tab open. >6. In a new tab, get the barcode for an item that has an itemtype >matching the circulation rule you just set. >7. Go to the checkouts for a patron that has a categorycode matching the >circulation rule you just set. >8. Check out your item. Confirm that the checkout is due at the end of >the loan period, not taking closing hours into consideration. Return the >item. >9. Back in your other tab, set ConsiderLibraryHoursWhenIssuing to >'close', so the due date should be shortened to meet the close time. >10. Check out your item. Confirm the checkout is due when the library >closes. Return the item. >11. Back in your other tab, set ConsiderLibraryHoursWhenIssuing to >'open', so the due date should be extended to meet the opening time. >12. Check out your item. Confirm the checkout is due the next day when >the library opens. >13. Confirm tests pass t/db_dependent/Circulation/CalcDateDue.t > >Sponsored-by: Catalyst IT >--- > C4/Circulation.pm | 65 ++++++++++++++++++- > t/db_dependent/Circulation/CalcDateDue.t | 83 +++++++++++++++++++++++- > 2 files changed, 143 insertions(+), 5 deletions(-) > >diff --git a/C4/Circulation.pm b/C4/Circulation.pm >index 0f1b6914aa6..92351b75d4c 100644 >--- a/C4/Circulation.pm >+++ b/C4/Circulation.pm >@@ -63,6 +63,7 @@ use Koha::SearchEngine::Indexer; > use Koha::Exceptions::Checkout; > use Koha::Plugins; > use Koha::Recalls; >+use Koha::Library::Hours; > use Carp qw( carp ); > use List::MoreUtils qw( any ); > use Scalar::Util qw( looks_like_number blessed ); >@@ -3821,11 +3822,43 @@ sub CalcDateDue { > } > ); > >+ my $considerlibraryhours = C4::Context->preference('ConsiderLibraryHoursWhenIssuing'); >+ # starter vars so don't do calculations directly to $datedue >+ my $potential_datedue = $datedue->clone; >+ my $library_close = $datedue->clone; >+ my $dayofweek = $datedue->local_day_of_week - 1; >+ my $todayhours = Koha::Library::Hours->find({ branchcode => $branch, day => $dayofweek }); >+ my @close = undef; >+ my $tomorrowhours = Koha::Library::Hours->find({ branchcode => $branch, day => $dayofweek+1 }); # get open hours of next day >+ my @open = undef; >+ if ( $todayhours->close_time and $tomorrowhours->open_time ) { >+ @close = split( ":", $todayhours->close_time ); >+ $library_close = $library_close->set( hour => $close[0], minute => $close[1] ); >+ $potential_datedue = $potential_datedue->add( hours => $loanlength->{$length_key} ); # datedue without consideration for open hours >+ @open = split( ":", $tomorrowhours->open_time ); >+ } >+ > # calculate the datedue as normal > if ( $daysmode eq 'Days' ) > { # ignoring calendar > if ( $loanlength->{lengthunit} eq 'hours' ) { >- $datedue->add( hours => $loanlength->{$length_key} ); >+ if ( $potential_datedue > $library_close and $todayhours->close_time and $tomorrowhours->open_time ) { >+ if ( $considerlibraryhours eq 'close' ) { >+ # datedue will be after the library closes on that day >+ # shorten loan period to end when library closes >+ $datedue->set( hour => $close[0], minute => $close[1] ); >+ } elsif ( $considerlibraryhours eq 'open' ) { >+ # datedue will be after the library closes on that day >+ # extend loan period to when library opens following day >+ $datedue->add( days => 1 )->set( hour => $open[0], minute => $open[1] ); >+ } else { >+ # ignore library open hours >+ $datedue->add( hours => $loanlength->{$length_key} ); >+ } >+ } else { >+ # due time doesn't conflict with library open hours, don't need to check >+ $datedue->add( hours => $loanlength->{$length_key} ); >+ } > } else { # days > $datedue->add( days => $loanlength->{$length_key} ); > $datedue->set_hour(23); >@@ -3833,17 +3866,43 @@ sub CalcDateDue { > } > } else { > my $dur; >+ my $sethours; > if ($loanlength->{lengthunit} eq 'hours') { >- $dur = DateTime::Duration->new( hours => $loanlength->{$length_key}); >+ if ( $potential_datedue > $library_close and $todayhours->close_time and $tomorrowhours->open_time ) { >+ if ( $considerlibraryhours eq 'close' ) { >+ # datedue will be after the library closes on that day >+ # shorten loan period to end when library closes >+ $dur = $potential_datedue->delta_ms( $library_close ); >+ $sethours = $considerlibraryhours; >+ } elsif ( $considerlibraryhours eq 'open' ) { >+ # datedue will be after the library closes on that day >+ # extend loan period to when library opens following day >+ my $library_open = $datedue->clone->set( hour => $open[0], minute => $open[1] ); >+ $dur = $potential_datedue->delta_ms( $library_open )->add( days => 1 ); >+ $sethours = $considerlibraryhours; >+ } else { >+ # ignore library open hours >+ $dur = DateTime::Duration->new( hours => $loanlength->{$length_key} ); >+ } >+ } else { >+ # due time doesn't conflict with library open hours, don't need to check >+ $dur = DateTime::Duration->new( hours => $loanlength->{$length_key} ); >+ } > } > else { # days >- $dur = DateTime::Duration->new( days => $loanlength->{$length_key}); >+ $dur = DateTime::Duration->new( days => $loanlength->{$length_key} ); > } > my $calendar = Koha::Calendar->new( branchcode => $branch, days_mode => $daysmode ); > $datedue = $calendar->addDuration( $datedue, $dur, $loanlength->{lengthunit} ); > if ($loanlength->{lengthunit} eq 'days') { > $datedue->set_hour(23); > $datedue->set_minute(59); >+ } else { >+ if ( $sethours and $sethours eq 'close' ) { >+ $datedue->set( hour => $close[0], minute => $close[1] ); >+ } elsif ( $sethours and $sethours eq 'open' ) { >+ $datedue->set( hour => $open[0], minute => $open[1] ); >+ } > } > } > >diff --git a/t/db_dependent/Circulation/CalcDateDue.t b/t/db_dependent/Circulation/CalcDateDue.t >index cdcd8008700..faa1f4af35b 100755 >--- a/t/db_dependent/Circulation/CalcDateDue.t >+++ b/t/db_dependent/Circulation/CalcDateDue.t >@@ -2,14 +2,15 @@ > > use Modern::Perl; > >-use Test::More tests => 19; >+use Test::More tests => 23; > use Test::MockModule; > use DBI; > use DateTime; > use t::lib::Mocks; > use t::lib::TestBuilder; > use C4::Calendar qw( new insert_single_holiday delete_holiday insert_week_day_holiday ); >- >+use Koha::DateUtils qw( dt_from_string ); >+use Koha::Library::Hour; > use Koha::CirculationRules; > > use_ok('C4::Circulation', qw( CalcDateDue )); >@@ -340,5 +341,83 @@ my $renewed_date = $start_date->clone->add( days => 7 ); > $date = C4::Circulation::CalcDateDue( $start_date, $itemtype, $branchcode, $borrower, 1 ); > is( $date->ymd, $renewed_date->ymd, 'Renewal period of "" should trigger fallover to issuelength for renewal' ); > >+# Testing hourly loans consider library open hours >+ >+my $library1 = $builder->build( { source => 'Branch' } ); >+Koha::CirculationRules->set_rules( >+ { >+ categorycode => $categorycode, >+ itemtype => $itemtype, >+ branchcode => $library1->{branchcode}, >+ rules => { >+ issuelength => 3, # loan period is 3 hours >+ lengthunit => 'hours', >+ } >+ } >+); >+ >+my $open = DateTime->now->subtract( hours => 4 )->hms; >+my $close = DateTime->now->add( hours => 2 )->hms; >+my $now = DateTime->now; >+ >+foreach (0..6) { >+ # library opened 4 hours ago and closes in 2 hours. >+ Koha::Library::Hour->new({ day => $_, branchcode => $library1->{branchcode}, open_time => $open, close_time => $close })->store; >+} >+ >+# ignore calendar >+t::lib::Mocks::mock_preference('useDaysMode', 'Days'); >+t::lib::Mocks::mock_preference('ConsiderLibraryHoursWhenIssuing', 'close'); >+# shorten loan period >+ >+$date = C4::Circulation::CalcDateDue( $now, $itemtype, $library1->{branchcode}, $borrower ); >+my $expected_duetime = DateTime->now->add( hours => 2 ); >+is( $date, $expected_duetime, "Loan period was shortened because ConsiderLibraryHoursWhenIssuing is set to close time" ); >+ >+t::lib::Mocks::mock_preference('ConsiderLibraryHoursWhenIssuing', 'open'); >+# extend loan period >+ >+$date = C4::Circulation::CalcDateDue( $now, $itemtype, $library1->{branchcode}, $borrower ); >+$expected_duetime = DateTime->now->add( days => 1 )->subtract( hours => 4 ); >+is( $date, $expected_duetime, "Loan period was extended because ConsiderLibraryHoursWhenIssuing is set to open time" ); >+ >+my $holiday_tomorrow = DateTime->now->add( days => 1 ); >+ >+# consider calendar >+my $library1_calendar = C4::Calendar->new( branchcode => $library1->{branchcode} ); >+$library1_calendar->insert_single_holiday( >+ day => $holiday_tomorrow->day, >+ month => $holiday_tomorrow->month, >+ year => $holiday_tomorrow->year, >+ title => 'testholiday', >+ description => 'testholiday' >+); >+Koha::CirculationRules->set_rules( >+ { >+ categorycode => $categorycode, >+ itemtype => $itemtype, >+ branchcode => $library1->{branchcode}, >+ rules => { >+ issuelength => 13, # loan period must cross over into tomorrow >+ lengthunit => 'hours', >+ } >+ } >+); >+ >+t::lib::Mocks::mock_preference('useDaysMode', 'Calendar'); >+t::lib::Mocks::mock_preference('ConsiderLibraryHoursWhenIssuing', 'close'); >+# shorten loan period >+ >+$date = C4::Circulation::CalcDateDue( $now, $itemtype, $library1->{branchcode}, $borrower ); >+$expected_duetime = DateTime->now->add( days => 2, hours => 2 ); >+is( $date, $expected_duetime, "Loan period was shortened (but considers the holiday) because ConsiderLibraryHoursWhenIssuing is set to close time" ); >+ >+t::lib::Mocks::mock_preference('ConsiderLibraryHoursWhenIssuing', 'open'); >+# extend loan period >+ >+$date = C4::Circulation::CalcDateDue( $now, $itemtype, $library1->{branchcode}, $borrower ); >+$expected_duetime = DateTime->now->add( days => 2 )->subtract( hours => 4 ); >+is( $date, $expected_duetime, "Loan period was extended (but considers the holiday) because ConsiderLibraryHoursWhenIssuing is set to open time" ); >+ > $cache->clear_from_cache($key); > $schema->storage->txn_rollback; >-- >2.30.2
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
|
Splinter Review
Attachments on
bug 6796
:
124669
|
124670
|
124671
|
124672
|
134323
|
134324
|
134325
|
134326
|
134327
|
145669
|
145670
|
145671
|
145672
|
145673
|
146988
|
146989
|
146990
|
146991
|
146992
|
150442
|
150443
|
150444
|
150445
|
150446
|
150447
|
150448
|
150477
|
150478
|
153252
|
153253
|
153254
|
153255
|
153256
|
153257
|
153258
|
153259
|
153260
|
153261
|
153271
|
153272
|
153273
|
153274
|
153275
|
153276
|
153277
|
153278
|
153279
|
153280
|
156772
|
156773
|
156774
|
156775
|
156776
|
156777
|
156778
|
156779
|
156780
|
161970
|
161971
|
161972
|
161973
|
161974
|
161975
|
161976
|
161977
|
161978
|
161979
|
161980
|
161986
|
161987
|
161988
|
161989
|
162043
|
162044
|
162045
|
162046
|
162047
|
162048
|
162049
|
162050
|
162051
|
162052
|
162053
|
162054
|
162055
|
162056
|
162090
|
162091
|
162092
|
162093
|
162094
|
162095
|
162096
|
162097
|
162098
|
162099
|
162100
|
162101
|
162102
|
162103
|
162104
|
164511
|
164512
|
164513
|
164514
|
164515
|
164516
|
164517
|
164518
|
164538
|
164539
|
164540
|
164541
|
164542
|
164543
|
164544
|
164545
|
164546
|
164547
|
164548
|
164549
|
164550
|
164551
|
164552