View | Details | Raw Unified | Return to bug 6796
Collapse All | Expand All

(-)a/C4/Circulation.pm (-3 / +63 lines)
Lines 63-68 use Koha::SearchEngine::Indexer; Link Here
63
use Koha::Exceptions::Checkout;
63
use Koha::Exceptions::Checkout;
64
use Koha::Plugins;
64
use Koha::Plugins;
65
use Koha::Recalls;
65
use Koha::Recalls;
66
use Koha::Library::Hours;
66
use Carp qw( carp );
67
use Carp qw( carp );
67
use List::MoreUtils qw( any );
68
use List::MoreUtils qw( any );
68
use Scalar::Util qw( looks_like_number blessed );
69
use Scalar::Util qw( looks_like_number blessed );
Lines 3844-3854 sub CalcDateDue { Link Here
3844
        }
3845
        }
3845
    );
3846
    );
3846
3847
3848
    my $considerlibraryhours = C4::Context->preference('ConsiderLibraryHoursInCirculation');
3849
3850
    # starter vars so don't do calculations directly to $datedue
3851
    my $potential_datedue = $datedue->clone;
3852
    my $library_close = $datedue->clone;
3853
    my $dayofweek = $datedue->local_day_of_week - 1;
3854
    my $todayhours = Koha::Library::Hours->find({ library_id => $branch, day => $dayofweek });
3855
    my @close = undef;
3856
    my $tomorrowhours = Koha::Library::Hours->find({ library_id => $branch, day => $dayofweek+1 }); # get open hours of next day
3857
    my @open = undef;
3858
    if ( $todayhours->close_time and $tomorrowhours->open_time ) {
3859
        @close = split( ":", $todayhours->close_time );
3860
        $library_close = $library_close->set( hour => $close[0], minute => $close[1] );
3861
        $potential_datedue = $potential_datedue->add( hours => $loanlength->{$length_key} ); # datedue without consideration for open hours
3862
        @open = split( ":", $tomorrowhours->open_time );
3863
    }
3864
3847
    # calculate the datedue as normal
3865
    # calculate the datedue as normal
3848
    if ( $daysmode eq 'Days' )
3866
    if ( $daysmode eq 'Days' )
3849
    {    # ignoring calendar
3867
    {    # ignoring calendar
3850
        if ( $loanlength->{lengthunit} eq 'hours' ) {
3868
        if ( $loanlength->{lengthunit} eq 'hours' ) {
3851
            $datedue->add( hours => $loanlength->{$length_key} );
3869
            if ( $potential_datedue > $library_close and $todayhours->close_time and $tomorrowhours->open_time ) {
3870
                if ( $considerlibraryhours eq 'close' ) {
3871
                    # datedue will be after the library closes on that day
3872
                    # shorten loan period to end when library closes
3873
                    $datedue->set( hour => $close[0], minute => $close[1] );
3874
                } elsif ( $considerlibraryhours eq 'open' ) {
3875
                    # datedue will be after the library closes on that day
3876
                    # extend loan period to when library opens following day
3877
                    $datedue->add( days => 1 )->set( hour => $open[0], minute => $open[1] );
3878
                } else {
3879
                    # ignore library open hours
3880
                    $datedue->add( hours => $loanlength->{$length_key} );
3881
                }
3882
            } else {
3883
                # due time doesn't conflict with library open hours, don't need to check
3884
                $datedue->add( hours => $loanlength->{$length_key} );
3885
            }
3852
        } else {    # days
3886
        } else {    # days
3853
            $datedue->add( days => $loanlength->{$length_key} );
3887
            $datedue->add( days => $loanlength->{$length_key} );
3854
            $datedue->set_hour(23);
3888
            $datedue->set_hour(23);
Lines 3856-3872 sub CalcDateDue { Link Here
3856
        }
3890
        }
3857
    } else {
3891
    } else {
3858
        my $dur;
3892
        my $dur;
3893
        my $sethours;
3859
        if ($loanlength->{lengthunit} eq 'hours') {
3894
        if ($loanlength->{lengthunit} eq 'hours') {
3860
            $dur = DateTime::Duration->new( hours => $loanlength->{$length_key});
3895
            if ( $potential_datedue > $library_close and $todayhours->close_time and $tomorrowhours->open_time ) {
3896
                if ( $considerlibraryhours eq 'close' ) {
3897
                    # datedue will be after the library closes on that day
3898
                    # shorten loan period to end when library closes
3899
                    $dur = $potential_datedue->delta_ms( $library_close );
3900
                    $sethours = $considerlibraryhours;
3901
                } elsif ( $considerlibraryhours eq 'open' ) {
3902
                    # datedue will be after the library closes on that day
3903
                    # extend loan period to when library opens following day
3904
                    my $library_open = $datedue->clone->set( hour => $open[0], minute => $open[1] );
3905
                    $dur = $potential_datedue->delta_ms( $library_open )->add( days => 1 );
3906
                    $sethours = $considerlibraryhours;
3907
                } else {
3908
                    # ignore library open hours
3909
                    $dur = DateTime::Duration->new( hours => $loanlength->{$length_key} );
3910
                }
3911
            } else {
3912
                # due time doesn't conflict with library open hours, don't need to check
3913
                $dur = DateTime::Duration->new( hours => $loanlength->{$length_key} );
3914
            }
3861
        }
3915
        }
3862
        else { # days
3916
        else { # days
3863
            $dur = DateTime::Duration->new( days => $loanlength->{$length_key});
3917
            $dur = DateTime::Duration->new( days => $loanlength->{$length_key} );
3864
        }
3918
        }
3865
        my $calendar = Koha::Calendar->new( branchcode => $branch, days_mode => $daysmode );
3919
        my $calendar = Koha::Calendar->new( branchcode => $branch, days_mode => $daysmode );
3866
        $datedue = $calendar->addDuration( $datedue, $dur, $loanlength->{lengthunit} );
3920
        $datedue = $calendar->addDuration( $datedue, $dur, $loanlength->{lengthunit} );
3867
        if ($loanlength->{lengthunit} eq 'days') {
3921
        if ($loanlength->{lengthunit} eq 'days') {
3868
            $datedue->set_hour(23);
3922
            $datedue->set_hour(23);
3869
            $datedue->set_minute(59);
3923
            $datedue->set_minute(59);
3924
        } else {
3925
            if ( $sethours and $sethours eq 'close' ) {
3926
                $datedue->set( hour => $close[0], minute => $close[1] );
3927
            } elsif ( $sethours and $sethours eq 'open' ) {
3928
                $datedue->set( hour => $open[0], minute => $open[1] );
3929
            }
3870
        }
3930
        }
3871
    }
3931
    }
3872
3932
(-)a/t/db_dependent/Circulation/CalcDateDue.t (-4 / +82 lines)
Lines 2-15 Link Here
2
2
3
use Modern::Perl;
3
use Modern::Perl;
4
4
5
use Test::More tests => 19;
5
use Test::More tests => 23;
6
use Test::MockModule;
6
use Test::MockModule;
7
use DBI;
7
use DBI;
8
use DateTime;
8
use DateTime;
9
use t::lib::Mocks;
9
use t::lib::Mocks;
10
use t::lib::TestBuilder;
10
use t::lib::TestBuilder;
11
use C4::Calendar qw( new insert_single_holiday delete_holiday insert_week_day_holiday );
11
use C4::Calendar qw( new insert_single_holiday delete_holiday insert_week_day_holiday );
12
12
use Koha::DateUtils qw( dt_from_string );
13
use Koha::Library::Hours;
13
use Koha::CirculationRules;
14
use Koha::CirculationRules;
14
15
15
use_ok('C4::Circulation', qw( CalcDateDue ));
16
use_ok('C4::Circulation', qw( CalcDateDue ));
Lines 18-24 my $schema = Koha::Database->new->schema; Link Here
18
$schema->storage->txn_begin;
19
$schema->storage->txn_begin;
19
my $builder = t::lib::TestBuilder->new;
20
my $builder = t::lib::TestBuilder->new;
20
21
21
22
t::lib::Mocks::mock_preference( 'ConsiderLibraryHoursInCirculation', 'ignore' );
22
my $library = $builder->build_object({ class => 'Koha::Libraries' })->store;
23
my $library = $builder->build_object({ class => 'Koha::Libraries' })->store;
23
my $dateexpiry = '2013-01-01';
24
my $dateexpiry = '2013-01-01';
24
my $patron_category = $builder->build_object({ class => 'Koha::Patron::Categories', value => { category_type => 'B' } })->store;
25
my $patron_category = $builder->build_object({ class => 'Koha::Patron::Categories', value => { category_type => 'B' } })->store;
Lines 356-360 my $renewed_date = $start_date->clone->add( days => 7 ); Link Here
356
$date = C4::Circulation::CalcDateDue( $start_date, $itemtype, $branchcode, $borrower, 1 );
357
$date = C4::Circulation::CalcDateDue( $start_date, $itemtype, $branchcode, $borrower, 1 );
357
is( $date->ymd, $renewed_date->ymd, 'Renewal period of "" should trigger fallover to issuelength for renewal' );
358
is( $date->ymd, $renewed_date->ymd, 'Renewal period of "" should trigger fallover to issuelength for renewal' );
358
359
360
# Testing hourly loans consider library open hours
361
362
my $library1 = $builder->build( { source => 'Branch' } );
363
Koha::CirculationRules->set_rules(
364
    {
365
        categorycode => $categorycode,
366
        itemtype     => $itemtype,
367
        branchcode   => $library1->{branchcode},
368
        rules        => {
369
            issuelength   => 3, # loan period is 3 hours
370
            lengthunit    => 'hours',
371
        }
372
    }
373
);
374
375
my $open = DateTime->now->subtract( hours => 4 )->hms;
376
my $close = DateTime->now->add( hours => 2 )->hms;
377
my $now = DateTime->now;
378
379
foreach (0..6) {
380
    # library opened 4 hours ago and closes in 2 hours.
381
    Koha::Library::Hour->new({ day => $_, library_id => $library1->{branchcode}, open_time => $open, close_time => $close })->store;
382
}
383
384
# ignore calendar
385
t::lib::Mocks::mock_preference('useDaysMode', 'Days');
386
t::lib::Mocks::mock_preference('ConsiderLibraryHoursInCirculation', 'close');
387
# shorten loan period
388
389
$date = C4::Circulation::CalcDateDue( $now, $itemtype, $library1->{branchcode}, $borrower );
390
my $expected_duetime = DateTime->now->add( hours => 2 );
391
is( $date, $expected_duetime, "Loan period was shortened because ConsiderLibraryHoursInCirculation is set to close time" );
392
393
t::lib::Mocks::mock_preference('ConsiderLibraryHoursWhenIssuing', 'open');
394
# extend loan period
395
396
$date = C4::Circulation::CalcDateDue( $now, $itemtype, $library1->{branchcode}, $borrower );
397
$expected_duetime = DateTime->now->add( days => 1 )->subtract( hours => 4 );
398
is( $date, $expected_duetime, "Loan period was extended because ConsiderLibraryHoursInCirculation is set to open time" );
399
400
my $holiday_tomorrow = DateTime->now->add( days => 1 );
401
402
# consider calendar
403
my $library1_calendar = C4::Calendar->new( branchcode => $library1->{branchcode} );
404
$library1_calendar->insert_single_holiday(
405
    day             => $holiday_tomorrow->day,
406
    month           => $holiday_tomorrow->month,
407
    year            => $holiday_tomorrow->year,
408
    title           => 'testholiday',
409
    description     => 'testholiday'
410
);
411
Koha::CirculationRules->set_rules(
412
    {
413
        categorycode => $categorycode,
414
        itemtype     => $itemtype,
415
        branchcode   => $library1->{branchcode},
416
        rules        => {
417
            issuelength   => 13, # loan period must cross over into tomorrow
418
            lengthunit    => 'hours',
419
        }
420
    }
421
);
422
423
t::lib::Mocks::mock_preference('useDaysMode', 'Calendar');
424
t::lib::Mocks::mock_preference('ConsiderLibraryHoursInCirculation', 'close');
425
# shorten loan period
426
427
$date = C4::Circulation::CalcDateDue( $now, $itemtype, $library1->{branchcode}, $borrower );
428
$expected_duetime = DateTime->now->add( days => 2, hours => 2 );
429
is( $date, $expected_duetime, "Loan period was shortened (but considers the holiday) because ConsiderLibraryHoursInCirculation is set to close time" );
430
431
t::lib::Mocks::mock_preference( 'ConsiderLibraryHoursInCirculation', 'open' );
432
# extend loan period
433
434
$date = C4::Circulation::CalcDateDue( $now, $itemtype, $library1->{branchcode}, $borrower );
435
$expected_duetime = DateTime->now->add( days => 2 )->subtract( hours => 4 );
436
is( $date, $expected_duetime, "Loan period was extended (but considers the holiday) because ConsiderLibraryHoursInCirculation is set to open time" );
437
359
$cache->clear_from_cache($key);
438
$cache->clear_from_cache($key);
360
$schema->storage->txn_rollback;
439
$schema->storage->txn_rollback;
361
- 

Return to bug 6796