@@ -, +, @@
---
C4/Circulation.pm | 11 +-
C4/Overdues.pm | 4 +-
Koha/Calendar.pm | 2 +-
.../prog/en/modules/admin/smart-rules.tt | 3 +-
misc/cronjobs/fines.pl | 2 +-
t/Circulation/minuteloan.t | 166 ++++++++++++++++++++
6 files changed, 181 insertions(+), 7 deletions(-)
create mode 100755 t/Circulation/minuteloan.t
--- a/C4/Circulation.pm
+++ a/C4/Circulation.pm
@@ -2104,6 +2104,8 @@ sub _debar_user_on_return {
# finedays is in days, so hourly loans must multiply by 24
# thus 1 hour late equals 1 day suspension * finedays rate
$finedays = $finedays * 24 if ( $unit eq 'hours' );
+ $finedays = $finedays * 24 * 60 if ( $unit eq 'minutes' );
+
# grace period is measured in the same units as the loan
my $grace =
@@ -3234,8 +3236,8 @@ C<$isrenewal> = Boolean: is true if we want to calculate the date due for a rene
sub CapDateDue{
my ( $calcDueDate, $loanlength, $branch) = @_;
- # for hourly loans, we will limit the due date to close time
- return $calcDueDate unless ($loanlength->{lengthunit} eq 'hours');
+ # for hours and minutes, we will limit the due date to close time
+ return $calcDueDate unless ($loanlength->{lengthunit} eq 'hours' || $loanlength->{lengthunit} eq 'minutes');
# my $now = DateTime->now( time_zone => C4::Context->tz() );
my $branchHours = getOpeningHours();
@@ -3286,6 +3288,8 @@ sub CalcDateDue {
} else {
$datedue->add( hours => $loanlength->{issuelength} );
}
+ } elsif ( $loanlength->{lengthunit} eq 'minutes' ) {
+ $datedue->add( minutes => $loanlength->{issuelength} );
}else { # days
$datedue->add( days => $loanlength->{$length_key} );
$datedue->set_hour(23);
@@ -3296,6 +3300,9 @@ sub CalcDateDue {
if ($loanlength->{lengthunit} eq 'hours') {
$dur = DateTime::Duration->new( hours => $loanlength->{$length_key});
}
+ elsif ($loanlength->{lengthunit} eq 'minutes') {
+ $dur = DateTime::Duration->new( minutes => $loanlength->{issuelength});
+ }
else { # days
$dur = DateTime::Duration->new( days => $loanlength->{$length_key});
}
--- a/C4/Overdues.pm
+++ a/C4/Overdues.pm
@@ -139,7 +139,7 @@ LEFT JOIN biblioitems USING (biblioitemnumber)
}
if($params->{'shortrun'}){
- $statement .= " and issuingrules.lengthunit in ('hours') " ;
+ $statement .= " and issuingrules.lengthunit in ('hours', 'minutes') " ;
}
$statement .= 'ORDER BY borrowernumber';
@@ -292,7 +292,7 @@ sub _get_chargeable_units {
my ($unit, $dt1, $dt2, $branchcode, $openingHours) = @_;
my $charge_units = 0;
my $charge_duration;
- if ($unit eq 'hours') {
+ if ($unit eq 'hours' || $unit eq 'minutes') {
if(C4::Context->preference('finesCalendar') eq 'noFinesWhenClosed') {
if (!defined $openingHours->{$branchcode}{'Calendar'}){
$openingHours->{$branchcode}{'Calendar'} = Koha::Calendar->new( branchcode => $branchcode );
--- a/Koha/Calendar.pm
+++ a/Koha/Calendar.pm
@@ -125,7 +125,7 @@ sub addDate {
$unit ||= 'days'; # default days ?
my $dt;
- if ( $unit eq 'hours' ) {
+ if ( $unit eq 'hours' || $unit eq 'minutes') {
# Fixed for legacy support. Should be set as a branch parameter
Readonly::Scalar my $return_by_hour => 10;
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/smart-rules.tt
+++ a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/smart-rules.tt
@@ -242,6 +242,7 @@ for="tobranch">Clone these rules to:
+
@@ -253,7 +254,7 @@ for="tobranch">Clone these rules to:
[% INCLUDE 'date-format.inc' %]
|
- |
+ |
|
|
|
--- a/misc/cronjobs/fines.pl
+++ a/misc/cronjobs/fines.pl
@@ -65,7 +65,7 @@ This script has the following parameters :
-l --log: log the output to a file (optional if the -o parameter is given)
-o --out: ouput directory for logs (defaults to env or /tmp if !exist)
-v --verbose
- -s --short: only verifies the short duration borrowing (hourly)
+ -s --short: only verifies the short duration borrowing (minutes and hourly ones)
ENDUSAGE
--- a/t/Circulation/minuteloan.t
+++ a/t/Circulation/minuteloan.t
@@ -0,0 +1,166 @@
+#!/usr/bin/env perl
+
+use strict;
+use warnings;
+use Data::Dumper;
+use DateTime;
+use DateTime::Duration;
+use Test::More tests => 7;
+use Test::MockModule;
+use DBD::Mock;
+use Koha::DateUtils;
+use C4::Calendar qw(getOpeningHours);
+use C4::Circulation qw(CalcDateDue);
+use C4::Overdues qw(_get_chargeable_units Getoverdues);
+
+BEGIN {
+ die "DBD::Mock v$DBD::Mock::VERSION is too old. This test requires v1.45 or higher.", 33
+ unless $DBD::Mock::VERSION >= 1.45;
+
+ use_ok('Koha::Calendar');
+ use_ok('C4::Calendar');
+ use_ok('C4::Circulation');
+ use_ok('C4::Overdues');
+}
+
+my $module_context = new Test::MockModule('C4::Context');
+$module_context->mock(
+ '_new_dbh',
+ sub {
+ my $dbh = DBI->connect( 'DBI:Mock:', '', '' )
+ || die "Cannot create handle: $DBI::errstr\n";
+ return $dbh;
+ }
+);
+
+# Initialize the global $dbh variable
+my $dbh = C4::Context->dbh();
+
+{ # C4::Circulation
+ $module_context->mock('preference',sub {return 'Calendar';});
+
+ my $sessionCirc = DBD::Mock::Session->new('sessionCirc' => (
+ {
+ statement => qr/\s*SELECT issuelength, lengthunit, renewalperiod/,
+ results => [
+ [ 'issuelength', 'lengthunit', 'renewalperiod' ],
+ [ 30, 'minutes' , 0 ]
+ ]
+ },
+ {
+ statement => 'SELECT weekday FROM repeatable_holidays WHERE branchcode = ? AND weekday IS NOT NULL',
+ results => DBD::Mock->NULL_RESULTSET
+ },
+ {
+ statement => 'SELECT day, month FROM repeatable_holidays WHERE branchcode = ? AND weekday IS NULL',
+ results => [
+ ['day', 'month'],
+ [24,6]
+ ]
+ },
+ {
+ statement => 'SELECT day, month, year FROM special_holidays WHERE branchcode = ? AND isexception = 1',
+ results => DBD::Mock->NULL_RESULTSET
+ },
+ {
+ statement => 'SELECT day, month, year FROM special_holidays WHERE branchcode = ? AND isexception = 0',
+ results => DBD::Mock->NULL_RESULTSET
+ },
+ { #GetIssuingRules called in GetHardDueDate
+ statement => qr/select \* from issuingrules/,
+ results => [
+ ['hardduedate', 'hardduedatecompare'],
+ [undef,-1]
+ ]
+ },
+ { #Opening hours
+ statement => 'SELECT * FROM openinghours ',
+ results => [
+ ['branchcode', 'weekcode', 'openhour', 'closehour'],
+ ['BIB', 0, '09:00:00', '17:00:00'],
+ ['BIB', 1, '09:00:00', '17:00:00'],
+ ['BIB', 2, '09:00:00', '17:00:00'],
+ ['BIB', 3, '09:00:00', '17:00:00'],
+ ['BIB', 4, '09:00:00', '17:00:00'],
+ ['BIB', 5, '09:00:00', '17:00:00'],
+ ['BIB', 6, '09:00:00', '17:00:00']
+ ]
+ }
+ ));
+ $dbh->{ mock_session } = $sessionCirc;
+ print "\nTesting C4::Circulation\n";
+ is(CalcDateDue(dt_from_string('2014-06-23T16:40:00', 'iso'), 0, 'BIB',{categorycode => 0, dateexpiry => '2020'}, 0), dt_from_string('2014-06-23T17:00:00', 'iso'), "Testing minute loans. Due time capped at close time.");
+}
+
+{ #C4::Overdues
+ print "\nTesting C4::Overdues\n";
+ $module_context->mock('preference',sub {return 'noFinesWhenClosed';});
+ print " finesCalendar syspref set to 'noFinesWhenClosed'\n";
+ my $sessionOver = DBD::Mock::Session->new('sessionOver' =>(
+ { #Opening hours TEST #6
+ statement => 'SELECT * FROM openinghours ',
+ results => [
+ ['branchcode', 'weekcode', 'openhour', 'closehour'],
+ ['BIB', 0, '09:00:00', '17:00:00'],
+ ['BIB', 1, '09:00:00', '17:00:00'],
+ ['BIB', 2, '09:00:00', '17:00:00'],
+ ['BIB', 3, '09:00:00', '17:00:00'],
+ ['BIB', 4, '09:00:00', '17:00:00'],
+ ['BIB', 5, '09:00:00', '17:00:00'],
+ ['BIB', 6, '09:00:00', '17:00:00']
+ ]
+ },
+ {
+ statement => 'SELECT weekday FROM repeatable_holidays WHERE branchcode = ? AND weekday IS NOT NULL',
+ results => DBD::Mock->NULL_RESULTSET
+ },
+ {
+ statement => 'SELECT day, month FROM repeatable_holidays WHERE branchcode = ? AND weekday IS NULL',
+ results => [
+ ['day', 'month'],
+ [24,6]
+ ]
+ },
+ { #Opening hours TEST #7
+ statement => 'SELECT * FROM openinghours ',
+ results => [
+ ['branchcode', 'weekcode', 'openhour', 'closehour'],
+ ['BIB', 0, '09:00:00', '17:00:00'],
+ ['BIB', 1, '09:00:00', '17:00:00'],
+ ['BIB', 2, '09:00:00', '17:00:00'],
+ ['BIB', 3, '09:00:00', '17:00:00'],
+ ['BIB', 4, '09:00:00', '17:00:00'],
+ ['BIB', 5, '09:00:00', '17:00:00'],
+ ['BIB', 6, '09:00:00', '17:00:00']
+ ]
+ },
+ {
+ statement => qr/select \* from issuingrules/,
+ results => [
+ [ 'issuelength', 'lengthunit', 'fine', 'chargeperiod', 'firstremind'],
+ [ 30, 'minutes' , 0.25, 1, 0 ]
+ ]
+ },
+ {
+ statement => 'SELECT weekday FROM repeatable_holidays WHERE branchcode = ? AND weekday IS NOT NULL',
+ results => DBD::Mock->NULL_RESULTSET
+ },
+ {
+ statement => 'SELECT day, month FROM repeatable_holidays WHERE branchcode = ? AND weekday IS NULL',
+ results => DBD::Mock->NULL_RESULTSET
+ },
+ {
+ statement => 'SELECT day, month, year FROM special_holidays WHERE branchcode = ? AND isexception = 1',
+ results => DBD::Mock->NULL_RESULTSET
+ },
+ {
+ statement => 'SELECT day, month, year FROM special_holidays WHERE branchcode = ? AND isexception = 0',
+ results => DBD::Mock->NULL_RESULTSET
+ }
+ ));
+ $dbh->{ mock_session } = $sessionOver;
+ is(_get_chargeable_units('minutes', dt_from_string('2014-06-23T12:00:00', 'iso'), dt_from_string('2014-06-25T10:00:00', 'iso'), 'BIB', getOpeningHours()), 360, "Test if _get_chargeable_units takes opening hours and holidays into account.");
+
+ my ($fine) = CalcFine( {itemtype=>'item'}, 0, 'BIB' ,dt_from_string('2014-6-23T12:00:00', 'iso'), dt_from_string('2014-6-23T13:00:00', 'iso'), getOpeningHours());
+ is($fine, 15, 'Fines are calculated correctly for minute loans');
+}
--