use strict;
#use warnings; FIXME - Bug 2505
+use DateTime;
use C4::Context;
use C4::Stats;
use C4::Reserves;
use C4::Items;
use C4::Members;
use C4::Dates;
-use C4::Calendar;
+use C4::Dates qw(format_date);
use C4::Accounts;
use C4::ItemCirculationAlertPreference;
-use C4::Dates qw(format_date);
use C4::Message;
use C4::Debug;
-use Date::Calc qw(
- Today
- Today_and_Now
- Add_Delta_YM
- Add_Delta_DHMS
- Date_to_Days
- Day_of_Week
- Add_Delta_Days
- check_date
- Delta_Days
-);
-use POSIX qw(strftime);
use C4::Branch; # GetBranches
use C4::Log; # logaction
use Data::Dumper;
+use Koha::DateUtils;
+use Koha::Calendar;
+use Carp;
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
my $branch_borrower_circ_rule = GetBranchBorrowerCircRule($branch, $cat_borrower);
if (defined($branch_borrower_circ_rule->{maxissueqty})) {
my @bind_params = ();
- my $branch_count_query = "SELECT COUNT(*) FROM issues
+ my $branch_count_query = "SELECT COUNT(*) FROM issues
JOIN items USING (itemnumber)
WHERE borrowernumber = ? ";
push @bind_params, $borrower->{borrowernumber};
#
# DUE DATE is OK ? -- should already have checked.
#
+ if ($duedate && ref $duedate ne 'DateTime') {
+ $duedate = dt_from_string($duedate);
+ }
+ my $now = DateTime->now( time_zone => C4::Context->tz() );
unless ( $duedate ) {
- my $issuedate = strftime( "%Y-%m-%d", localtime );
+ my $issuedate = $now->clone();
my $branch = _GetCircControlBranch($item,$borrower);
my $itype = ( C4::Context->preference('item-level_itypes') ) ? $item->{'itype'} : $biblioitem->{'itemtype'};
- $duedate = CalcDateDue( C4::Dates->new( $issuedate, 'iso' ), $itype, $branch, $borrower );
+ $duedate = CalcDateDue( $issuedate, $itype, $branch, $borrower );
# Offline circ calls AddIssue directly, doesn't run through here
# So issuingimpossible should be ok.
}
if ($duedate) {
- $needsconfirmation{INVALID_DATE} = $duedate->output('syspref')
- unless $duedate->output('iso') ge C4::Dates->today('iso');
+ my $today = $now->clone();
+ $today->truncate( to => 'minutes');
+ if (DateTime->compare($duedate,$today) == -1 ) { # duedate cannot be before now
+ $needsconfirmation{INVALID_DATE} = output_pref($duedate);
+ }
} else {
- $issuingimpossible{INVALID_DATE} = $duedate->output('syspref');
+ $issuingimpossible{INVALID_DATE} = output_pref($duedate);
}
#
if ( $borrower->{flags}->{'DBARRED'} ) {
$issuingimpossible{DEBARRED} = 1;
}
- if ( $borrower->{'dateexpiry'} eq '0000-00-00') {
+ if ( !defined $borrower->{dateexpiry} || $borrower->{'dateexpiry'} eq '0000-00-00') {
$issuingimpossible{EXPIRED} = 1;
} else {
- my @expirydate= split /-/,$borrower->{'dateexpiry'};
- if($expirydate[0]==0 || $expirydate[1]==0|| $expirydate[2]==0 ||
- Date_to_Days(Today) > Date_to_Days( @expirydate )) {
- $issuingimpossible{EXPIRED} = 1;
+ my ($y, $m, $d) = split /-/,$borrower->{'dateexpiry'};
+ if ($y && $m && $d) { # are we really writing oinvalid dates to borrs
+ my $expiry_dt = DateTime->new(
+ year => $y,
+ month => $m,
+ day => $d,
+ time_zone => C4::Context->tz,
+ );
+ $expiry_dt->truncate( to => 'days');
+ my $today = $now->clone()->truncate(to => 'days');
+ if (DateTime->compare($today, $expiry_dt) == 1) {
+ $issuingimpossible{EXPIRED} = 1;
+ }
+ } else {
+ carp("Invalid expity date in borr");
+ $issuingimpossible{EXPIRED} = 1;
}
}
#
# DEBTS
my ($amount) =
- C4::Members::GetMemberAccountRecords( $borrower->{'borrowernumber'}, '' && $duedate->output('iso') );
+ C4::Members::GetMemberAccountRecords( $borrower->{'borrowernumber'}, '' && $duedate->ymd() );
my $amountlimit = C4::Context->preference("noissuescharge");
my $allowfineoverride = C4::Context->preference("AllowFineOverride");
my $allfinesneedoverride = C4::Context->preference("AllFinesNeedOverride");
#
my ($current_loan_count, $max_loans_allowed) = TooMany( $borrower, $item->{biblionumber}, $item );
# if TooMany max_loans_allowed returns 0 the user doesn't have permission to check out this book
- if ($max_loans_allowed eq 0) {
+ if (defined $max_loans_allowed && $max_loans_allowed == 0) {
$needsconfirmation{PATRON_CANT} = 1;
} else {
if($max_loans_allowed){
my ( $borrower, $barcode, $datedue, $cancelreserve, $issuedate, $sipmode) = @_;
my $dbh = C4::Context->dbh;
my $barcodecheck=CheckValidBarcode($barcode);
+ if ($datedue && ref $datedue ne 'DateTime') {
+ $datedue = dt_from_string($datedue);
+ }
# $issuedate defaults to today.
if ( ! defined $issuedate ) {
- $issuedate = strftime( "%Y-%m-%d", localtime );
- # TODO: for hourly circ, this will need to be a C4::Dates object
- # and all calls to AddIssue including issuedate will need to pass a Dates object.
+ $issuedate = DateTime->now(time_zone => C4::Context->tz());
}
- if ($borrower and $barcode and $barcodecheck ne '0'){
+ else {
+ if ( ref $issuedate ne 'DateTime') {
+ $issuedate = dt_from_string($issuedate);
+
+ }
+ }
+ if ($borrower and $barcode and $barcodecheck ne '0'){#??? wtf
# find which item we issue
my $item = GetItem('', $barcode) or return undef; # if we don't get an Item, abort.
my $branch = _GetCircControlBranch($item,$borrower);
# check if we just renew the issue.
#
if ($actualissue->{borrowernumber} eq $borrower->{'borrowernumber'}) {
- $datedue = AddRenewal(
- $borrower->{'borrowernumber'},
- $item->{'itemnumber'},
- $branch,
- $datedue,
- $issuedate, # here interpreted as the renewal date
+ $datedue = AddRenewal(
+ $borrower->{'borrowernumber'},
+ $item->{'itemnumber'},
+ $branch,
+ $datedue,
+ $issuedate, # here interpreted as the renewal date
);
}
else {
}
MoveReserve( $item->{'itemnumber'}, $borrower->{'borrowernumber'}, $cancelreserve );
-
# Starting process for transfer job (checking transfert and validate it if we have one)
my ($datesent) = GetTransfers($item->{'itemnumber'});
if ($datesent) {
# Record in the database the fact that the book was issued.
my $sth =
$dbh->prepare(
- "INSERT INTO issues
+ "INSERT INTO issues
(borrowernumber, itemnumber,issuedate, date_due, branchcode)
VALUES (?,?,?,?,?)"
);
unless ($datedue) {
my $itype = ( C4::Context->preference('item-level_itypes') ) ? $biblio->{'itype'} : $biblio->{'itemtype'};
- $datedue = CalcDateDue( C4::Dates->new( $issuedate, 'iso' ), $itype, $branch, $borrower );
+ $datedue = CalcDateDue( $issuedate, $itype, $branch, $borrower );
}
+ $datedue->truncate( to => 'minutes');
$sth->execute(
$borrower->{'borrowernumber'}, # borrowernumber
$item->{'itemnumber'}, # itemnumber
- $issuedate, # issuedate
- $datedue->output('iso'), # date_due
+ $issuedate->strftime('%Y-%m-%d %H:%M:00'), # issuedate
+ $datedue->strftime('%Y-%m-%d %H:%M:00'), # date_due
C4::Context->userenv->{'branch'} # branchcode
);
- $sth->finish;
if ( C4::Context->preference('ReturnToShelvingCart') ) { ## ReturnToShelvingCart is on, anything issued should be taken off the cart.
CartToShelf( $item->{'itemnumber'} );
}
ModItem({ issues => $item->{'issues'},
holdingbranch => C4::Context->userenv->{'branch'},
itemlost => 0,
- datelastborrowed => C4::Dates->new()->output('iso'),
- onloan => $datedue->output('iso'),
+ datelastborrowed => DateTime->now(time_zone => C4::Context->tz())->ymd(),
+ onloan => $datedue->ymd(),
}, $item->{'biblionumber'}, $item->{'itemnumber'});
ModDateLastSeen( $item->{'itemnumber'} );
my $dbh = C4::Context->dbh;
my $sth =
$dbh->prepare(
-"select issuelength from issuingrules where categorycode=? and itemtype=? and branchcode=? and issuelength is not null"
+'select issuelength, lengthunit from issuingrules where categorycode=? and itemtype=? and branchcode=? and issuelength is not null'
);
# warn "in get loan lenght $borrowertype $itemtype $branchcode ";
# try to find issuelength & return the 1st available.
# check with borrowertype, itemtype and branchcode, then without one of those parameters
$sth->execute( $borrowertype, $itemtype, $branchcode );
my $loanlength = $sth->fetchrow_hashref;
- return $loanlength->{issuelength}
- if defined($loanlength) && $loanlength->{issuelength} ne 'NULL';
+ return $loanlength
+ if defined($loanlength) && $loanlength->{issuelength};
- $sth->execute( $borrowertype, "*", $branchcode );
+ $sth->execute( $borrowertype, '*', $branchcode );
$loanlength = $sth->fetchrow_hashref;
- return $loanlength->{issuelength}
- if defined($loanlength) && $loanlength->{issuelength} ne 'NULL';
+ return $loanlength
+ if defined($loanlength) && $loanlength->{issuelength};
- $sth->execute( "*", $itemtype, $branchcode );
+ $sth->execute( '*', $itemtype, $branchcode );
$loanlength = $sth->fetchrow_hashref;
- return $loanlength->{issuelength}
- if defined($loanlength) && $loanlength->{issuelength} ne 'NULL';
+ return $loanlength
+ if defined($loanlength) && $loanlength->{issuelength};
- $sth->execute( "*", "*", $branchcode );
+ $sth->execute( '*', '*', $branchcode );
$loanlength = $sth->fetchrow_hashref;
- return $loanlength->{issuelength}
- if defined($loanlength) && $loanlength->{issuelength} ne 'NULL';
+ return $loanlength
+ if defined($loanlength) && $loanlength->{issuelength};
- $sth->execute( $borrowertype, $itemtype, "*" );
+ $sth->execute( $borrowertype, $itemtype, '*' );
$loanlength = $sth->fetchrow_hashref;
- return $loanlength->{issuelength}
- if defined($loanlength) && $loanlength->{issuelength} ne 'NULL';
+ return $loanlength
+ if defined($loanlength) && $loanlength->{issuelength};
- $sth->execute( $borrowertype, "*", "*" );
+ $sth->execute( $borrowertype, '*', '*' );
$loanlength = $sth->fetchrow_hashref;
- return $loanlength->{issuelength}
- if defined($loanlength) && $loanlength->{issuelength} ne 'NULL';
+ return $loanlength
+ if defined($loanlength) && $loanlength->{issuelength};
- $sth->execute( "*", $itemtype, "*" );
+ $sth->execute( '*', $itemtype, '*' );
$loanlength = $sth->fetchrow_hashref;
- return $loanlength->{issuelength}
- if defined($loanlength) && $loanlength->{issuelength} ne 'NULL';
+ return $loanlength
+ if defined($loanlength) && $loanlength->{issuelength};
- $sth->execute( "*", "*", "*" );
+ $sth->execute( '*', '*', '*' );
$loanlength = $sth->fetchrow_hashref;
- return $loanlength->{issuelength}
- if defined($loanlength) && $loanlength->{issuelength} ne 'NULL';
+ return $loanlength
+ if defined($loanlength) && $loanlength->{issuelength};
# if no rule is set => 21 days (hardcoded)
- return 21;
+ return {
+ issuelength => 21,
+ lengthunit => 'days',
+ };
+
}
);
$sth->execute( $borrowertype, $itemtype, $branchcode );
my $results = $sth->fetchrow_hashref;
- return (C4::Dates->new($results->{hardduedate}, 'iso'),$results->{hardduedatecompare})
- if defined($results) && $results->{hardduedate} ne 'NULL';
+ return (dt_from_string($results->{hardduedate}, 'iso'),$results->{hardduedatecompare})
+ if defined($results) && $results->{hardduedate};
$sth->execute( $borrowertype, "*", $branchcode );
$results = $sth->fetchrow_hashref;
- return (C4::Dates->new($results->{hardduedate}, 'iso'),$results->{hardduedatecompare})
- if defined($results) && $results->{hardduedate} ne 'NULL';
+ return (dt_from_string($results->{hardduedate}, 'iso'),$results->{hardduedatecompare})
+ if defined($results) && $results->{hardduedate};
$sth->execute( "*", $itemtype, $branchcode );
$results = $sth->fetchrow_hashref;
- return (C4::Dates->new($results->{hardduedate}, 'iso'),$results->{hardduedatecompare})
- if defined($results) && $results->{hardduedate} ne 'NULL';
+ return (dt_from_string($results->{hardduedate}, 'iso'),$results->{hardduedatecompare})
+ if defined($results) && $results->{hardduedate};
$sth->execute( "*", "*", $branchcode );
$results = $sth->fetchrow_hashref;
- return (C4::Dates->new($results->{hardduedate}, 'iso'),$results->{hardduedatecompare})
- if defined($results) && $results->{hardduedate} ne 'NULL';
+ return (dt_from_string($results->{hardduedate}, 'iso'),$results->{hardduedatecompare})
+ if defined($results) && $results->{hardduedate};
$sth->execute( $borrowertype, $itemtype, "*" );
$results = $sth->fetchrow_hashref;
- return (C4::Dates->new($results->{hardduedate}, 'iso'),$results->{hardduedatecompare})
- if defined($results) && $results->{hardduedate} ne 'NULL';
+ return (dt_from_string($results->{hardduedate}, 'iso'),$results->{hardduedatecompare})
+ if defined($results) && $results->{hardduedate};
$sth->execute( $borrowertype, "*", "*" );
$results = $sth->fetchrow_hashref;
- return (C4::Dates->new($results->{hardduedate}, 'iso'),$results->{hardduedatecompare})
- if defined($results) && $results->{hardduedate} ne 'NULL';
+ return (dt_from_string($results->{hardduedate}, 'iso'),$results->{hardduedatecompare})
+ if defined($results) && $results->{hardduedate};
$sth->execute( "*", $itemtype, "*" );
$results = $sth->fetchrow_hashref;
- return (C4::Dates->new($results->{hardduedate}, 'iso'),$results->{hardduedatecompare})
- if defined($results) && $results->{hardduedate} ne 'NULL';
+ return (dt_from_string($results->{hardduedate}, 'iso'),$results->{hardduedatecompare})
+ if defined($results) && $results->{hardduedate};
$sth->execute( "*", "*", "*" );
$results = $sth->fetchrow_hashref;
- return (C4::Dates->new($results->{hardduedate}, 'iso'),$results->{hardduedatecompare})
- if defined($results) && $results->{hardduedate} ne 'NULL';
+ return (dt_from_string($results->{hardduedate}, 'iso'),$results->{hardduedatecompare})
+ if defined($results) && $results->{hardduedate};
# if no rule is set => return undefined
return (undef, undef);
Retrieves circulation rule attributes that apply to the given
branch and item type, regardless of patron category.
- The return value is a hashref containing the following key:
+ The return value is a hashref containing the following keys:
holdallowed => Hold policy for this branch and itemtype. Possible values:
0: No holds allowed.
1: Holds allowed only by patrons that have the same homebranch as the item.
2: Holds allowed from any patron.
+ returnbranch => branch to which to return item. Possible values:
+ noreturn: do not return, let item remain where checked in (floating collections)
+ homebranch: return to item's home branch
+
This searches branchitemrules in the following order:
* Same branchcode and itemtype
* branchcode '*', same itemtype
* branchcode and itemtype '*'
- Neither C<$branchcode> nor C<$categorycode> should be '*'.
+ Neither C<$branchcode> nor C<$itemtype> should be '*'.
=cut
my $result = {};
my @attempts = (
- ['SELECT holdallowed
+ ['SELECT holdallowed, returnbranch
FROM branch_item_rules
WHERE branchcode = ?
AND itemtype = ?', $branchcode, $itemtype],
- ['SELECT holdallowed
+ ['SELECT holdallowed, returnbranch
FROM default_branch_circ_rules
WHERE branchcode = ?', $branchcode],
- ['SELECT holdallowed
+ ['SELECT holdallowed, returnbranch
FROM default_branch_item_rules
WHERE itemtype = ?', $itemtype],
- ['SELECT holdallowed
+ ['SELECT holdallowed, returnbranch
FROM default_circ_rules'],
);
foreach my $attempt (@attempts) {
my ($query, @bind_params) = @{$attempt};
+ my $search_result = $dbh->selectrow_hashref ( $query , {}, @bind_params );
# Since branch/category and branch/itemtype use the same per-branch
# defaults tables, we have to check that the key we want is set, not
# just that a row was returned
- return $result if ( defined( $result->{'holdallowed'} = $dbh->selectrow_array( $query, {}, @bind_params ) ) );
+ $result->{'holdallowed'} = $search_result->{'holdallowed'} unless ( defined $result->{'holdallowed'} );
+ $result->{'returnbranch'} = $search_result->{'returnbranch'} unless ( defined $result->{'returnbranch'} );
}
# built-in default circulation rule
- return {
- holdallowed => 2,
- };
+ $result->{'holdallowed'} = 2 unless ( defined $result->{'holdallowed'} );
+ $result->{'returnbranch'} = 'homebranch' unless ( defined $result->{'returnbranch'} );
+
+ return $result;
}
=head2 AddReturn
my $item = GetItem($itemnumber) or die "GetItem($itemnumber) failed";
# full item data, but no borrowernumber or checkout info (no issue)
# we know GetItem should work because GetItemnumberFromBarcode worked
- my $hbr = C4::Context->preference("HomeOrHoldingBranchReturn") || "homebranch";
- $hbr = $item->{$hbr} || '';
- # item must be from items table -- issues table has branchcode and issuingbranch, not homebranch nor holdingbranch
+ my $hbr = GetBranchItemRule($item->{'homebranch'}, $item->{'itype'})->{'returnbranch'} || "homebranch";
+ # get the proper branch to which to return the item
+ $hbr = $item->{$hbr} || $branch ;
+ # if $hbr was "noreturn" or any other non-item table value, then it should 'float' (i.e. stay at this branch)
my $borrowernumber = $borrower->{'borrowernumber'} || undef; # we don't know if we had a borrower or not
# define circControlBranch only if dropbox mode is set
# don't allow dropbox mode to create an invalid entry in issues (issuedate > today)
# FIXME: check issuedate > returndate, factoring in holidays
- $circControlBranch = _GetCircControlBranch($item,$borrower) unless ( $item->{'issuedate'} eq C4::Dates->today('iso') );;
+ #$circControlBranch = _GetCircControlBranch($item,$borrower) unless ( $item->{'issuedate'} eq C4::Dates->today('iso') );;
+ $circControlBranch = _GetCircControlBranch($item,$borrower);
}
if ($borrowernumber) {
sub MarkIssueReturned {
my ( $borrowernumber, $itemnumber, $dropbox_branch, $returndate, $privacy ) = @_;
my $dbh = C4::Context->dbh;
- my $query = "UPDATE issues SET returndate=";
+ my $query = 'UPDATE issues SET returndate=';
my @bind;
if ($dropbox_branch) {
- my $calendar = C4::Calendar->new( branchcode => $dropbox_branch );
- my $dropboxdate = $calendar->addDate( C4::Dates->new(), -1 );
- $query .= " ? ";
- push @bind, $dropboxdate->output('iso');
+ my $calendar = Koha::Calendar->new( branchcode => $dropbox_branch );
+ my $dropboxdate = $calendar->addDate( DateTime->now( time_zone => C4::Context->tz), -1 );
+ $query .= ' ? ';
+ push @bind, $dropboxdate->strftime('%Y-%m-%d %H:%M');
} elsif ($returndate) {
- $query .= " ? ";
+ $query .= ' ? ';
push @bind, $returndate;
} else {
- $query .= " now() ";
+ $query .= ' now() ';
}
- $query .= " WHERE borrowernumber = ? AND itemnumber = ?";
+ $query .= ' WHERE borrowernumber = ? AND itemnumber = ?';
push @bind, $borrowernumber, $itemnumber;
# FIXME transaction
my $sth_upd = $dbh->prepare($query);
$sth_upd->execute(@bind);
- my $sth_copy = $dbh->prepare("INSERT INTO old_issues SELECT * FROM issues
+ my $sth_copy = $dbh->prepare('INSERT INTO old_issues SELECT * FROM issues
WHERE borrowernumber = ?
- AND itemnumber = ?");
+ AND itemnumber = ?');
$sth_copy->execute($borrowernumber, $itemnumber);
# anonymise patron checkout immediately if $privacy set to 2 and AnonymousPatron is set to a valid borrowernumber
if ( $privacy == 2) {
sub _FixFineDaysOnReturn {
my ( $borrower, $item, $datedue ) = @_;
-
- if ($datedue) {
- $datedue = C4::Dates->new( $datedue, "iso" );
- } else {
- return;
- }
+ return unless ($datedue);
+
+ my $dt_due = dt_from_string( $datedue );
+ my $dt_today = DateTime->now( time_zone => C4::Context->tz() );
my $branchcode = _GetCircControlBranch( $item, $borrower );
- my $calendar = C4::Calendar->new( branchcode => $branchcode );
- my $today = C4::Dates->new();
+ my $calendar = Koha::Calendar->new( branchcode => $branchcode );
- my $deltadays = $calendar->daysBetween( $datedue, C4::Dates->new() );
+ # $deltadays is a DateTime::Duration object
+ my $deltadays = $calendar->days_between( $dt_due, $dt_today );
my $circcontrol = C4::Context::preference('CircControl');
my $issuingrule = GetIssuingRule( $borrower->{categorycode}, $item->{itype}, $branchcode );
# exit if no finedays defined
return unless $finedays;
- my $grace = $issuingrule->{firstremind};
-
- if ( $deltadays - $grace > 0 ) {
- my @newdate = Add_Delta_Days( Today(), $deltadays * $finedays );
- my $isonewdate = join( '-', @newdate );
- my ( $deby, $debm, $debd ) = split( /-/, $borrower->{debarred} );
- if ( check_date( $deby, $debm, $debd ) ) {
- my @olddate = split( /-/, $borrower->{debarred} );
-
- if ( Delta_Days( @olddate, @newdate ) > 0 ) {
- C4::Members::DebarMember( $borrower->{borrowernumber}, $isonewdate );
- return $isonewdate;
+ my $grace = DateTime::Duration->new( days => $issuingrule->{firstremind} );
+
+ if ( ( $deltadays - $grace )->is_positive ) { # you can't compare DateTime::Durations with logical operators
+ my $new_debar_dt = $dt_today->clone()->add_duration( $deltadays * $finedays );
+ my $borrower_debar_dt = dt_from_string( $borrower->{debarred} );
+ # check to see if the current debar date is a valid date
+ if ( $borrower->{debarred} && $borrower_debar_dt ) {
+ # if so, is it before the new date? update only if true
+ if ( DateTime->compare( $borrower_debar_dt, $new_debar_dt ) == -1 ) {
+ C4::Members::DebarMember( $borrower->{borrowernumber}, $new_debar_dt->ymd() );
+ return $new_debar_dt->ymd();
}
+ # if the borrower's debar date is not set or valid, debar them
} else {
- C4::Members::DebarMember( $borrower->{borrowernumber}, $isonewdate );
- return $isonewdate;
+ C4::Members::DebarMember( $borrower->{borrowernumber}, $new_debar_dt->ymd() );
+ return $new_debar_dt->ymd();
}
}
}
return unless $itemnumber;
my $sth = C4::Context->dbh->prepare(
"SELECT *
- FROM issues
+ FROM issues
LEFT JOIN items ON issues.itemnumber=items.itemnumber
WHERE issues.itemnumber=?");
$sth->execute($itemnumber);
my $data = $sth->fetchrow_hashref;
return unless $data;
- $data->{'overdue'} = ($data->{'date_due'} lt C4::Dates->today('iso')) ? 1 : 0;
- return ($data);
+ $data->{issuedate} = dt_from_string($data->{issuedate}, 'sql');
+ $data->{issuedate}->truncate(to => 'minutes');
+ $data->{date_due} = dt_from_string($data->{date_due}, 'sql');
+ $data->{date_due}->truncate(to => 'minutes');
+ my $dt = DateTime->now( time_zone => C4::Context->tz)->truncate( to => 'minutes');
+ $data->{'overdue'} = DateTime->compare($data->{'date_due'}, $dt ) == -1 ? 1 : 0;
+ return $data;
}
=head2 GetOpenIssue
sub GetItemIssues {
my ( $itemnumber, $history ) = @_;
- my $today = C4::Dates->today('iso'); # get today date
- my $sql = "SELECT * FROM issues
+ my $today = DateTime->now( time_zome => C4::Context->tz); # get today date
+ $today->truncate( to => 'minutes' );
+ my $sql = "SELECT * FROM issues
JOIN borrowers USING (borrowernumber)
JOIN items USING (itemnumber)
WHERE issues.itemnumber = ? ";
if ($history) {
$sql .= "UNION ALL
- SELECT * FROM old_issues
+ SELECT * FROM old_issues
LEFT JOIN borrowers USING (borrowernumber)
JOIN items USING (itemnumber)
WHERE old_issues.itemnumber = ? ";
}
my $results = $sth->fetchall_arrayref({});
foreach (@$results) {
- $_->{'overdue'} = ($_->{'date_due'} lt $today) ? 1 : 0;
+ my $date_due = dt_from_string($_->{date_due},'sql');
+ $date_due->truncate( to => 'minutes' );
+
+ $_->{overdue} = (DateTime->compare($date_due, $today) == -1) ? 1 : 0;
}
return $results;
}
SELECT
borrowers.categorycode, biblioitems.itemtype, issues.renewals, renewalsallowed, $controlbranch
FROM issuingrules,
- issues
+ issues
LEFT JOIN items USING (itemnumber)
LEFT JOIN borrowers USING (borrowernumber)
LEFT JOIN biblioitems USING (biblioitemnumber)
my $itemnumber = shift or return undef;
my $branch = shift;
my $datedue = shift;
- my $lastreneweddate = shift || C4::Dates->new()->output('iso');
+ my $lastreneweddate = shift || DateTime->now(time_zone => C4::Context->tz)->ymd();
my $item = GetItem($itemnumber) or return undef;
my $biblio = GetBiblioFromItemNumber($itemnumber) or return undef;
$sth->execute( $borrowernumber, $itemnumber );
my $issuedata = $sth->fetchrow_hashref;
$sth->finish;
- if($datedue && ! $datedue->output('iso')){
- warn "Invalid date passed to AddRenewal.";
- return undef;
+ if(defined $datedue && ref $datedue ne 'DateTime' ) {
+ carp 'Invalid date passed to AddRenewal.';
+ return;
}
# If the due date wasn't specified, calculate it by adding the
# book's loan length to today's date or the current due date
my $itemtype = (C4::Context->preference('item-level_itypes')) ? $biblio->{'itype'} : $biblio->{'itemtype'};
$datedue = (C4::Context->preference('RenewalPeriodBase') eq 'date_due') ?
- C4::Dates->new($issuedata->{date_due}, 'iso') :
- C4::Dates->new();
+ $issuedata->{date_due} :
+ DateTime->now( time_zone => C4::Context->tz());
$datedue = CalcDateDue($datedue,$itemtype,$issuedata->{'branchcode'},$borrower);
}
WHERE borrowernumber=?
AND itemnumber=?"
);
- $sth->execute( $datedue->output('iso'), $renews, $lastreneweddate, $borrowernumber, $itemnumber );
+
+ $sth->execute( $datedue->strftime('%Y-%m-%d %H:%M'), $renews, $lastreneweddate, $borrowernumber, $itemnumber );
$sth->finish;
# Update the renewal count on the item, and tell zebra to reindex
$renews = $biblio->{'renewals'} + 1;
- ModItem({ renewals => $renews, onloan => $datedue->output('iso') }, $biblio->{'biblionumber'}, $itemnumber);
+ ModItem({ renewals => $renews, onloan => $datedue->strftime('%Y-%m-%d %H:%M')}, $biblio->{'biblionumber'}, $itemnumber);
# Charge a new rental fee, if applicable?
my ( $charge, $type ) = GetIssuingCharges( $itemnumber, $borrowernumber );
$sth->execute( $borrowernumber, $accountno, $charge, $manager_id,
"Renewal of Rental Item $item->{'title'} $item->{'barcode'}",
'Rent', $charge, $itemnumber );
- $sth->finish;
}
# Log the renewal
UpdateStats( $branch, 'renew', $charge, '', $itemnumber, $item->{itype}, $borrowernumber);
=cut
-sub CalcDateDue {
- my ($startdate,$itemtype,$branch,$borrower) = @_;
- my $datedue;
- my $loanlength = GetLoanLength($borrower->{'categorycode'},$itemtype, $branch);
-
- # if globalDueDate ON the datedue is set to that date
- if ( C4::Context->preference('globalDueDate')
- && ( C4::Context->preference('globalDueDate') =~ C4::Dates->regexp('syspref') ) ) {
- $datedue = C4::Dates->new( C4::Context->preference('globalDueDate') );
- } else {
- # otherwise, calculate the datedue as normal
- if(C4::Context->preference('useDaysMode') eq 'Days') { # ignoring calendar
- my $timedue = time + ($loanlength) * 86400;
- #FIXME - assumes now even though we take a startdate
- my @datearr = localtime($timedue);
- $datedue = C4::Dates->new( sprintf("%04d-%02d-%02d", 1900 + $datearr[5], $datearr[4] + 1, $datearr[3]), 'iso');
- } else {
- my $calendar = C4::Calendar->new( branchcode => $branch );
- $datedue = $calendar->addDate($startdate, $loanlength);
- }
- }
+sub CalcDateDue {
+ my ( $startdate, $itemtype, $branch, $borrower ) = @_;
- # if Hard Due Dates are used, retreive them and apply as necessary
- my ($hardduedate, $hardduedatecompare) = GetHardDueDate($borrower->{'categorycode'},$itemtype, $branch);
- if ( $hardduedate && $hardduedate->output('iso') && $hardduedate->output('iso') ne '0000-00-00') {
- # if the calculated due date is after the 'before' Hard Due Date (ceiling), override
- if ( $datedue->output( 'iso' ) gt $hardduedate->output( 'iso' ) && $hardduedatecompare == -1) {
- $datedue = $hardduedate;
- # if the calculated date is before the 'after' Hard Due Date (floor), override
- } elsif ( $datedue->output( 'iso' ) lt $hardduedate->output( 'iso' ) && $hardduedatecompare == 1) {
- $datedue = $hardduedate;
- # if the hard due date is set to 'exactly', overrride
- } elsif ( $hardduedatecompare == 0) {
- $datedue = $hardduedate;
- }
- # in all other cases, keep the date due as it is
- }
+ # loanlength now a href
+ my $loanlength =
+ GetLoanLength( $borrower->{'categorycode'}, $itemtype, $branch );
- # if ReturnBeforeExpiry ON the datedue can't be after borrower expirydate
- if ( C4::Context->preference('ReturnBeforeExpiry') && $datedue->output('iso') gt $borrower->{dateexpiry} ) {
- $datedue = C4::Dates->new( $borrower->{dateexpiry}, 'iso' );
- }
-
- return $datedue;
-}
+ my $datedue;
-=head2 CheckValidDatedue
-
- $newdatedue = CheckValidDatedue($date_due,$itemnumber,$branchcode);
+ # if globalDueDate ON the datedue is set to that date
+ if (C4::Context->preference('globalDueDate')
+ && ( C4::Context->preference('globalDueDate') =~
+ C4::Dates->regexp('syspref') )
+ ) {
+ $datedue = dt_from_string(
+ C4::Context->preference('globalDueDate'),
+ C4::Context->preference('dateformat')
+ );
+ } else {
-This function does not account for holiday exceptions nor does it handle the 'useDaysMode' syspref .
-To be replaced by CalcDateDue() once C4::Calendar use is tested.
+ # otherwise, calculate the datedue as normal
+ if ( C4::Context->preference('useDaysMode') eq 'Days' )
+ { # ignoring calendar
+ my $dt =
+ DateTime->now( time_zone => C4::Context->tz() )
+ ->truncate( to => 'minute' );
+ if ( $loanlength->{lengthunit} eq 'hours' ) {
+ $dt->add( hours => $loanlength->{issuelength} );
+ return $dt;
+ } else { # days
+ $dt->add( days => $loanlength->{issuelength} );
+ $dt->set_hour(23);
+ $dt->set_minute(59);
+ return $dt;
+ }
+ } else {
+ my $dur;
+ if ($loanlength->{lengthunit} eq 'hours') {
+ $dur = DateTime::Duration->new( hours => $loanlength->{issuelength});
+ }
+ else { # days
+ $dur = DateTime::Duration->new( days => $loanlength->{issuelength});
+ }
+ if (ref $startdate ne 'DateTime' ) {
+ $startdate = dt_from_string($startdate);
+ }
+ my $calendar = Koha::Calendar->new( branchcode => $branch );
+ $datedue = $calendar->addDate( $startdate, $dur, $loanlength->{lengthunit} );
+ if ($loanlength->{lengthunit} eq 'days') {
+ $datedue->set_hour(23);
+ $datedue->set_minute(59);
+ }
+ }
+ }
-this function validates the loan length against the holidays calendar, and adjusts the due date as per the 'useDaysMode' syspref.
-C<$date_due> = returndate calculate with no day check
-C<$itemnumber> = itemnumber
-C<$branchcode> = location of issue (affected by 'CircControl' syspref)
-C<$loanlength> = loan length prior to adjustment
+ # if Hard Due Dates are used, retreive them and apply as necessary
+ my ( $hardduedate, $hardduedatecompare ) =
+ GetHardDueDate( $borrower->{'categorycode'}, $itemtype, $branch );
+ if ($hardduedate) { # hardduedates are currently dates
+ $hardduedate->truncate( to => 'minute' );
+ $hardduedate->set_hour(23);
+ $hardduedate->set_minute(59);
+ my $cmp = DateTime->compare( $hardduedate, $datedue );
+
+# if the calculated due date is after the 'before' Hard Due Date (ceiling), override
+# if the calculated date is before the 'after' Hard Due Date (floor), override
+# if the hard due date is set to 'exactly', overrride
+ if ( $hardduedatecompare == 0 || $hardduedatecompare == $cmp ) {
+ $datedue = $hardduedate->clone;
+ }
-=cut
+ # in all other cases, keep the date due as it is
+ }
-sub CheckValidDatedue {
-my ($date_due,$itemnumber,$branchcode)=@_;
-my @datedue=split('-',$date_due->output('iso'));
-my $years=$datedue[0];
-my $month=$datedue[1];
-my $day=$datedue[2];
-# die "Item# $itemnumber ($branchcode) due: " . ${date_due}->output() . "\n(Y,M,D) = ($years,$month,$day)":
-my $dow;
-for (my $i=0;$i<2;$i++){
- $dow=Day_of_Week($years,$month,$day);
- ($dow=0) if ($dow>6);
- my $result=CheckRepeatableHolidays($itemnumber,$dow,$branchcode);
- my $countspecial=CheckSpecialHolidays($years,$month,$day,$itemnumber,$branchcode);
- my $countspecialrepeatable=CheckRepeatableSpecialHolidays($month,$day,$itemnumber,$branchcode);
- if (($result ne '0') or ($countspecial ne '0') or ($countspecialrepeatable ne '0') ){
- $i=0;
- (($years,$month,$day) = Add_Delta_Days($years,$month,$day, 1))if ($i ne '1');
+ # if ReturnBeforeExpiry ON the datedue can't be after borrower expirydate
+ if ( C4::Context->preference('ReturnBeforeExpiry') ) {
+ my $expiry_dt = dt_from_string( $borrower->{dateexpiry}, 'iso' );
+ if ( DateTime->compare( $datedue, $expiry_dt ) == 1 ) {
+ $datedue = $expiry_dt->clone;
}
}
- my $newdatedue=C4::Dates->new(sprintf("%04d-%02d-%02d",$years,$month,$day),'iso');
-return $newdatedue;
+
+ return $datedue;
}
}
# save the values entered
elsif ($op eq 'add') {
- my $sth_search = $dbh->prepare("SELECT COUNT(*) AS total FROM issuingrules WHERE branchcode=? AND categorycode=? AND itemtype=?");
- my $sth_insert = $dbh->prepare("INSERT INTO issuingrules (branchcode, categorycode, itemtype, maxissueqty, renewalsallowed, reservesallowed, issuelength, hardduedate, hardduedatecompare, fine, finedays, firstremind, chargeperiod,rentaldiscount) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?)");
- my $sth_update=$dbh->prepare("UPDATE issuingrules SET fine=?, finedays=?, firstremind=?, chargeperiod=?, maxissueqty=?, renewalsallowed=?, reservesallowed=?, issuelength=?, hardduedate=?, hardduedatecompare=?, rentaldiscount=? WHERE branchcode=? AND categorycode=? AND itemtype=?");
+ my $sth_search = $dbh->prepare('SELECT COUNT(*) AS total FROM issuingrules WHERE branchcode=? AND categorycode=? AND itemtype=?');
+ my $sth_insert = $dbh->prepare('INSERT INTO issuingrules (branchcode, categorycode, itemtype, maxissueqty, renewalsallowed, reservesallowed, issuelength, lengthunit, hardduedate, hardduedatecompare, fine, finedays, firstremind, chargeperiod,rentaldiscount) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)');
+ my $sth_update=$dbh->prepare("UPDATE issuingrules SET fine=?, finedays=?, firstremind=?, chargeperiod=?, maxissueqty=?, renewalsallowed=?, reservesallowed=?, issuelength=?, lengthunit = ?, hardduedate=?, hardduedatecompare=?, rentaldiscount=? WHERE branchcode=? AND categorycode=? AND itemtype=?");
my $br = $branch; # branch
my $bor = $input->param('categorycode'); # borrower category
$maxissueqty =~ s/\s//g;
$maxissueqty = undef if $maxissueqty !~ /^\d+/;
my $issuelength = $input->param('issuelength');
+ my $lengthunit = $input->param('lengthunit');
my $hardduedate = $input->param('hardduedate');
$hardduedate = format_date_in_iso($hardduedate);
my $hardduedatecompare = $input->param('hardduedatecompare');
$sth_search->execute($br,$bor,$cat);
my $res = $sth_search->fetchrow_hashref();
if ($res->{total}) {
- $sth_update->execute($fine, $finedays,$firstremind, $chargeperiod, $maxissueqty, $renewalsallowed,$reservesallowed, $issuelength,$hardduedate,$hardduedatecompare,$rentaldiscount, $br,$bor,$cat);
+ $sth_update->execute($fine, $finedays,$firstremind, $chargeperiod, $maxissueqty, $renewalsallowed,$reservesallowed, $issuelength,$lengthunit, $hardduedate,$hardduedatecompare,$rentaldiscount, $br,$bor,$cat);
} else {
- $sth_insert->execute($br,$bor,$cat,$maxissueqty,$renewalsallowed,$reservesallowed,$issuelength,$hardduedate,$hardduedatecompare,$fine,$finedays,$firstremind,$chargeperiod,$rentaldiscount);
+ $sth_insert->execute($br,$bor,$cat,$maxissueqty,$renewalsallowed,$reservesallowed,$issuelength,$lengthunit,$hardduedate,$hardduedatecompare,$fine,$finedays,$firstremind,$chargeperiod,$rentaldiscount);
}
}
elsif ($op eq "set-branch-defaults") {
my $categorycode = $input->param('categorycode');
my $maxissueqty = $input->param('maxissueqty');
my $holdallowed = $input->param('holdallowed');
+ my $returnbranch = $input->param('returnbranch');
$maxissueqty =~ s/\s//g;
$maxissueqty = undef if $maxissueqty !~ /^\d+/;
$holdallowed =~ s/\s//g;
my $sth_search = $dbh->prepare("SELECT count(*) AS total
FROM default_circ_rules");
my $sth_insert = $dbh->prepare("INSERT INTO default_circ_rules
- (maxissueqty, holdallowed)
- VALUES (?, ?)");
+ (maxissueqty, holdallowed, returnbranch)
+ VALUES (?, ?, ?)");
my $sth_update = $dbh->prepare("UPDATE default_circ_rules
- SET maxissueqty = ?, holdallowed = ?");
+ SET maxissueqty = ?, holdallowed = ?, returnbranch = ?");
$sth_search->execute();
my $res = $sth_search->fetchrow_hashref();
if ($res->{total}) {
- $sth_update->execute($maxissueqty, $holdallowed);
+ $sth_update->execute($maxissueqty, $holdallowed, $returnbranch);
} else {
- $sth_insert->execute($maxissueqty, $holdallowed);
+ $sth_insert->execute($maxissueqty, $holdallowed, $returnbranch);
}
} else {
my $sth_search = $dbh->prepare("SELECT count(*) AS total
FROM default_branch_circ_rules
WHERE branchcode = ?");
my $sth_insert = $dbh->prepare("INSERT INTO default_branch_circ_rules
- (branchcode, maxissueqty, holdallowed)
- VALUES (?, ?, ?)");
+ (branchcode, maxissueqty, holdallowed, returnbranch)
+ VALUES (?, ?, ?, ?)");
my $sth_update = $dbh->prepare("UPDATE default_branch_circ_rules
- SET maxissueqty = ?, holdallowed = ?
+ SET maxissueqty = ?, holdallowed = ?, returnbranch = ?
WHERE branchcode = ?");
$sth_search->execute($branch);
my $res = $sth_search->fetchrow_hashref();
if ($res->{total}) {
- $sth_update->execute($maxissueqty, $holdallowed, $branch);
+ $sth_update->execute($maxissueqty, $holdallowed, $returnbranch, $branch);
} else {
- $sth_insert->execute($branch, $maxissueqty, $holdallowed);
+ $sth_insert->execute($branch, $maxissueqty, $holdallowed, $returnbranch);
}
}
}
elsif ($op eq "add-branch-item") {
my $itemtype = $input->param('itemtype');
my $holdallowed = $input->param('holdallowed');
+ my $returnbranch = $input->param('returnbranch');
$holdallowed =~ s/\s//g;
$holdallowed = undef if $holdallowed !~ /^\d+/;
my $sth_search = $dbh->prepare("SELECT count(*) AS total
FROM default_circ_rules");
my $sth_insert = $dbh->prepare("INSERT INTO default_circ_rules
- (holdallowed)
- VALUES (?)");
+ (holdallowed, returnbranch)
+ VALUES (?, ?)");
my $sth_update = $dbh->prepare("UPDATE default_circ_rules
- SET holdallowed = ?");
+ SET holdallowed = ?, returnbranch = ?");
$sth_search->execute();
my $res = $sth_search->fetchrow_hashref();
if ($res->{total}) {
- $sth_update->execute($holdallowed);
+ $sth_update->execute($holdallowed, $returnbranch);
} else {
- $sth_insert->execute($holdallowed);
+ $sth_insert->execute($holdallowed, $returnbranch);
}
} else {
my $sth_search = $dbh->prepare("SELECT count(*) AS total
FROM default_branch_item_rules
WHERE itemtype = ?");
my $sth_insert = $dbh->prepare("INSERT INTO default_branch_item_rules
- (itemtype, holdallowed)
- VALUES (?, ?)");
+ (itemtype, holdallowed, returnbranch)
+ VALUES (?, ?, ?)");
my $sth_update = $dbh->prepare("UPDATE default_branch_item_rules
- SET holdallowed = ?
+ SET holdallowed = ?, returnbranch = ?
WHERE itemtype = ?");
$sth_search->execute($itemtype);
my $res = $sth_search->fetchrow_hashref();
if ($res->{total}) {
- $sth_update->execute($holdallowed, $itemtype);
+ $sth_update->execute($holdallowed, $returnbranch, $itemtype);
} else {
- $sth_insert->execute($itemtype, $holdallowed);
+ $sth_insert->execute($itemtype, $holdallowed, $returnbranch);
}
}
} elsif ($itemtype eq "*") {
FROM default_branch_circ_rules
WHERE branchcode = ?");
my $sth_insert = $dbh->prepare("INSERT INTO default_branch_circ_rules
- (branchcode, holdallowed)
- VALUES (?, ?)");
+ (branchcode, holdallowed, returnbranch)
+ VALUES (?, ?, ?)");
my $sth_update = $dbh->prepare("UPDATE default_branch_circ_rules
- SET holdallowed = ?
+ SET holdallowed = ?, returnbranch = ?
WHERE branchcode = ?");
$sth_search->execute($branch);
my $res = $sth_search->fetchrow_hashref();
if ($res->{total}) {
- $sth_update->execute($holdallowed, $branch);
+ $sth_update->execute($holdallowed, $returnbranch, $branch);
} else {
- $sth_insert->execute($branch, $holdallowed);
+ $sth_insert->execute($branch, $holdallowed, $returnbranch);
}
} else {
my $sth_search = $dbh->prepare("SELECT count(*) AS total
WHERE branchcode = ?
AND itemtype = ?");
my $sth_insert = $dbh->prepare("INSERT INTO branch_item_rules
- (branchcode, itemtype, holdallowed)
- VALUES (?, ?, ?)");
+ (branchcode, itemtype, holdallowed, returnbranch)
+ VALUES (?, ?, ?, ?)");
my $sth_update = $dbh->prepare("UPDATE branch_item_rules
- SET holdallowed = ?
+ SET holdallowed = ?, returnbranch = ?
WHERE branchcode = ?
AND itemtype = ?");
$sth_search->execute($branch, $itemtype);
my $res = $sth_search->fetchrow_hashref();
if ($res->{total}) {
- $sth_update->execute($holdallowed, $branch, $itemtype);
+ $sth_update->execute($holdallowed, $returnbranch, $branch, $itemtype);
} else {
- $sth_insert->execute($branch, $itemtype, $holdallowed);
+ $sth_insert->execute($branch, $itemtype, $holdallowed, $returnbranch);
}
}
}
$template->param(default_holdallowed_same => 1) if($defaults->{holdallowed} == 1);
$template->param(default_holdallowed_any => 1) if($defaults->{holdallowed} == 2);
$template->param(default_maxissueqty => $defaults->{maxissueqty});
+ $template->param(default_returnbranch => $defaults->{returnbranch});
}
$template->param(default_rules => ($defaults ? 1 : 0));
use C4::Items;
use C4::Branch;
use C4::Acquisition;
- use C4::Output;
+ use C4::Bookseller qw(GetBookSellerFromId);
+ use C4::Output; # contains gettemplate
use C4::Auth;
use C4::Serials;
- use C4::Dates qw/format_date/;
use C4::Circulation; # to use itemissues
use C4::Members; # to use GetMember
use C4::Search; # enabled_staff_search_views
use C4::Members qw/GetHideLostItemsPreference/;
+use Koha::DateUtils;
my $query=new CGI;
my $itemtypes = GetItemTypes;
$data->{'itemtypename'} = $itemtypes->{$data->{'itemtype'}}->{'description'};
-
+ $data->{'rentalcharge'} = sprintf( "%.2f", $data->{'rentalcharge'} );
foreach ( keys %{$data} ) {
$template->param( "$_" => defined $data->{$_} ? $data->{$_} : '' );
}
$item->{'collection'} = $ccodes->{ $item->{ccode} } if ($ccodes);
$item->{'itype'} = $itemtypes->{ $item->{'itype'} }->{'description'};
$item->{'replacementprice'} = sprintf( "%.2f", $item->{'replacementprice'} );
- $item->{$_} = format_date( $item->{$_} ) foreach qw/datelastborrowed dateaccessioned datelastseen lastreneweddate/;
$item->{'copyvol'} = $item->{'copynumber'};
-
# item has a host number if its biblio number does not match the current bib
if ($item->{biblionumber} ne $biblionumber){
$item->{hostbiblionumber} = $item->{biblionumber};
$item->{'ordernumber'} = $order->{'ordernumber'};
$item->{'basketno'} = $order->{'basketno'};
$item->{'booksellerinvoicenumber'} = $order->{'booksellerinvoicenumber'};
+ $item->{'orderdate'} = $order->{'entrydate'};
+ if ($item->{'basketno'}){
+ my $basket = GetBasket($item->{'basketno'});
+ my $bookseller = GetBookSellerFromId($basket->{'booksellerid'});
+ $item->{'vendor'} = $bookseller->{'name'};
+ }
$item->{'datereceived'} = $order->{'datereceived'};
if ($item->{notforloantext} or $item->{itemlost} or $item->{damaged} or $item->{wthdrawn}) {
}
$item->{'homebranchname'} = GetBranchName($item->{'homebranch'});
$item->{'holdingbranchname'} = GetBranchName($item->{'holdingbranch'});
- if ($item->{datedue}) {
- $item->{datedue} = format_sqldatetime($item->{datedue});
+ if ($item->{'datedue'}) {
$item->{'issue'}= 1;
} else {
$item->{'issue'}= 0;
use C4::Branch;
use C4::Debug;
use C4::Dates qw/format_date format_date_in_iso/;
-use Date::Calc qw/Today/;
use Text::CSV_XS;
+use Koha::DateUtils;
+use DateTime;
my $input = new CGI;
my $order = $input->param('order') || '';
my $op = $input->param('op') || '';
my $dateduefrom = format_date_in_iso($input->param( 'dateduefrom' )) || '';
my $datedueto = format_date_in_iso($input->param( 'datedueto' )) || '';
+# FIXME This is a kludge to include times
+if ($datedueto) {
+ $datedueto .= ' 23:59';
+}
+if ($dateduefrom) {
+ $dateduefrom .= ' 00:00';
+}
+# kludge end
my $isfiltered = $op =~ /apply/i && $op =~ /filter/i;
my $noreport = C4::Context->preference('FilterBeforeOverdueReport') && ! $isfiltered && $op ne "csv";
# FIX 2: ensure there are indexes for columns participating in the WHERE clauses, where feasible/reasonable
- my $todaysdate = sprintf("%-04.4d-%-02.2d-%02.2d", Today());
+ my $today_dt = DateTime->now(time_zone => C4::Context->tz);
+ $today_dt->truncate(to => 'minutes');
+ my $todaysdate = $today_dt->strftime('%Y-%m-%d %H:%M');
$bornamefilter =~s/\*/\%/g;
$bornamefilter =~s/\?/\_/g;
biblio.biblionumber,
borrowers.branchcode,
items.itemcallnumber,
- items.replacementprice
+ items.replacementprice,
+ items.enumchron
FROM issues
LEFT JOIN borrowers ON (issues.borrowernumber=borrowers.borrowernumber )
LEFT JOIN items ON (issues.itemnumber=items.itemnumber)
my @displayvalues = map { $_->[1] } @{ $pattrs->{$pattr_filter->{code}} }; # grab second value from each subarray
push @patron_attr_value_loop, { value => join(', ', sort { lc $a cmp lc $b } @displayvalues) };
}
+ my $dt = dt_from_string($data->{date_due}, 'sql');
push @overduedata, {
- duedate => format_date($data->{date_due}),
+ duedate => output_pref($dt),
borrowernumber => $data->{borrowernumber},
barcode => $data->{barcode},
itemnum => $data->{itemnumber},
branchcode => $data->{branchcode},
itemcallnumber => $data->{itemcallnumber},
replacementprice => $data->{replacementprice},
+ enumchron => $data->{enumchron},
patron_attr_value_loop => \@patron_attr_value_loop,
};
}
$template->param(
csv_param_string => $csv_param_string,
- todaysdate => format_date($todaysdate),
+ todaysdate => output_pref($today_dt),
overdueloop => \@overduedata,
nnoverdue => scalar(@overduedata),
noverdue_is_plural => scalar(@overduedata) != 1,
`branchcode` varchar(10) NOT NULL,
`itemtype` varchar(10) NOT NULL,
`holdallowed` tinyint(1) default NULL,
+ `returnbranch` varchar(15) default NULL,
PRIMARY KEY (`itemtype`,`branchcode`),
KEY `branch_item_rules_ibfk_2` (`branchcode`),
CONSTRAINT `branch_item_rules_ibfk_1` FOREIGN KEY (`itemtype`) REFERENCES `itemtypes` (`itemtype`)
`branchcode` VARCHAR(10) NOT NULL,
`maxissueqty` int(4) default NULL,
`holdallowed` tinyint(1) default NULL,
+ `returnbranch` varchar(15) default NULL,
PRIMARY KEY (`branchcode`),
CONSTRAINT `default_branch_circ_rules_ibfk_1` FOREIGN KEY (`branchcode`) REFERENCES `branches` (`branchcode`)
ON DELETE CASCADE ON UPDATE CASCADE
CREATE TABLE `default_branch_item_rules` (
`itemtype` varchar(10) NOT NULL,
`holdallowed` tinyint(1) default NULL,
+ `returnbranch` varchar(15) default NULL,
PRIMARY KEY (`itemtype`),
CONSTRAINT `default_branch_item_rules_ibfk_1` FOREIGN KEY (`itemtype`) REFERENCES `itemtypes` (`itemtype`)
ON DELETE CASCADE ON UPDATE CASCADE
`singleton` enum('singleton') NOT NULL default 'singleton',
`maxissueqty` int(4) default NULL,
`holdallowed` int(1) default NULL,
+ `returnbranch` varchar(15) default NULL,
PRIMARY KEY (`singleton`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `issues` ( -- information related to check outs or issues
`borrowernumber` int(11), -- foreign key, linking this to the borrowers table for the patron this item was checked out to
`itemnumber` int(11), -- foreign key, linking this to the items table for the item that was checked out
- `date_due` date default NULL, -- date the item is due (yyyy-mm-dd)
+ `date_due` datetime default NULL, -- datetime the item is due (yyyy-mm-dd hh:mm::ss)
`branchcode` varchar(10) default NULL, -- foreign key, linking to the branches table for the location the item was checked out
`issuingbranch` varchar(18) default NULL,
- `returndate` date default NULL, -- date the item was returned, will be NULL until moved to old_issues
- `lastreneweddate` date default NULL, -- date the item was last renewed
+ `returndate` datetime default NULL, -- date the item was returned, will be NULL until moved to old_issues
+ `lastreneweddate` datetime default NULL, -- date the item was last renewed
`return` varchar(4) default NULL,
`renewals` tinyint(4) default NULL, -- lists the number of times the item was renewed
`timestamp` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP, -- the date and time this record was last touched
- `issuedate` date default NULL, -- date the item was checked out or issued
+ `issuedate` datetime default NULL, -- date the item was checked out or issued
KEY `issuesborridx` (`borrowernumber`),
KEY `bordate` (`borrowernumber`,`timestamp`),
CONSTRAINT `issues_ibfk_1` FOREIGN KEY (`borrowernumber`) REFERENCES `borrowers` (`borrowernumber`) ON DELETE RESTRICT ON UPDATE CASCADE,
ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
+ -- Table structure for table `oai_sets`
+ --
+
+ DROP TABLE IF EXISTS `oai_sets`;
+ CREATE TABLE `oai_sets` (
+ `id` int(11) NOT NULL auto_increment,
+ `spec` varchar(80) NOT NULL UNIQUE,
+ `name` varchar(80) NOT NULL,
+ PRIMARY KEY (`id`)
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+ --
+ -- Table structure for table `oai_sets_descriptions`
+ --
+
+ DROP TABLE IF EXISTS `oai_sets_descriptions`;
+ CREATE TABLE `oai_sets_descriptions` (
+ `set_id` int(11) NOT NULL,
+ `description` varchar(255) NOT NULL,
+ CONSTRAINT `oai_sets_descriptions_ibfk_1` FOREIGN KEY (`set_id`) REFERENCES `oai_sets` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+ --
+ -- Table structure for table `oai_sets_mappings`
+ --
+
+ DROP TABLE IF EXISTS `oai_sets_mappings`;
+ CREATE TABLE `oai_sets_mappings` (
+ `set_id` int(11) NOT NULL,
+ `marcfield` char(3) NOT NULL,
+ `marcsubfield` char(1) NOT NULL,
+ `marcvalue` varchar(80) NOT NULL,
+ CONSTRAINT `oai_sets_mappings_ibfk_1` FOREIGN KEY (`set_id`) REFERENCES `oai_sets` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+ --
+ -- Table structure for table `oai_sets_biblios`
+ --
+
+ DROP TABLE IF EXISTS `oai_sets_biblios`;
+ CREATE TABLE `oai_sets_biblios` (
+ `biblionumber` int(11) NOT NULL,
+ `set_id` int(11) NOT NULL,
+ PRIMARY KEY (`biblionumber`, `set_id`),
+ CONSTRAINT `oai_sets_biblios_ibfk_1` FOREIGN KEY (`biblionumber`) REFERENCES `biblio` (`biblionumber`) ON DELETE CASCADE ON UPDATE CASCADE,
+ CONSTRAINT `oai_sets_biblios_ibfk_2` FOREIGN KEY (`set_id`) REFERENCES `oai_sets` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+ --
-- Table structure for table `old_issues`
--
CREATE TABLE `old_issues` ( -- lists items that were checked out and have been returned
`borrowernumber` int(11) default NULL, -- foreign key, linking this to the borrowers table for the patron this item was checked out to
`itemnumber` int(11) default NULL, -- foreign key, linking this to the items table for the item that was checked out
- `date_due` date default NULL, -- date the item is due (yyyy-mm-dd)
+ `date_due` datetime default NULL, -- date the item is due (yyyy-mm-dd)
`branchcode` varchar(10) default NULL, -- foreign key, linking to the branches table for the location the item was checked out
`issuingbranch` varchar(18) default NULL,
- `returndate` date default NULL, -- date the item was returned
- `lastreneweddate` date default NULL, -- date the item was last renewed
+ `returndate` datetime default NULL, -- date the item was returned
+ `lastreneweddate` datetime default NULL, -- date the item was last renewed
`return` varchar(4) default NULL,
`renewals` tinyint(4) default NULL, -- lists the number of times the item was renewed
`timestamp` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP, -- the date and time this record was last touched
- `issuedate` date default NULL, -- date the item was checked out or issued
+ `issuedate` datetime default NULL, -- date the item was checked out or issued
KEY `old_issuesborridx` (`borrowernumber`),
KEY `old_issuesitemidx` (`itemnumber`),
KEY `old_bordate` (`borrowernumber`,`timestamp`),
CREATE TABLE `virtualshelves` ( -- information about lists (or virtual shelves)
`shelfnumber` int(11) NOT NULL auto_increment, -- unique identifier assigned by Koha
`shelfname` varchar(255) default NULL, -- name of the list
- `owner` varchar(80) default NULL, -- foriegn key linking to the borrowers table (using borrowernumber) for the creator of this list
- `category` varchar(1) default NULL, -- type of list (public [2], private [1] or open [3])
+ `owner` int default NULL, -- foreign key linking to the borrowers table (using borrowernumber) for the creator of this list (changed from varchar(80) to int)
+ `category` varchar(1) default NULL, -- type of list (private [1], public [2])
`sortfield` varchar(16) default NULL, -- the field this list is sorted on
`lastmodified` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP, -- date and time the list was last modified
- PRIMARY KEY (`shelfnumber`)
+ `allow_add` tinyint(1) default 0, -- permission for adding entries to list
+ `allow_delete_own` tinyint(1) default 1, -- permission for deleting entries frm list that you added yourself
+ `allow_delete_other` tinyint(1) default 0, -- permission for deleting entries from list that another person added
+ PRIMARY KEY (`shelfnumber`),
+ CONSTRAINT `virtualshelves_ibfk_1` FOREIGN KEY (`owner`) REFERENCES `borrowers` (`borrowernumber`) ON DELETE SET NULL ON UPDATE SET NULL -- no cascaded delete, please see HandleDelBorrower in VirtualShelves.pm
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
`biblionumber` int(11) NOT NULL default 0, -- foreign key linking to the biblio table, defines the bib record that has been added to the list
`flags` int(11) default NULL,
`dateadded` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, -- date and time this bib record was added to the list
+ `borrowernumber` int, -- borrower number that created this list entry (only the first one is saved: no need for use in/as key)
KEY `shelfnumber` (`shelfnumber`),
KEY `biblionumber` (`biblionumber`),
CONSTRAINT `virtualshelfcontents_ibfk_1` FOREIGN KEY (`shelfnumber`) REFERENCES `virtualshelves` (`shelfnumber`) ON DELETE CASCADE ON UPDATE CASCADE,
- CONSTRAINT `shelfcontents_ibfk_2` FOREIGN KEY (`biblionumber`) REFERENCES `biblio` (`biblionumber`) ON DELETE CASCADE ON UPDATE CASCADE
+ CONSTRAINT `shelfcontents_ibfk_2` FOREIGN KEY (`biblionumber`) REFERENCES `biblio` (`biblionumber`) ON DELETE CASCADE ON UPDATE CASCADE,
+ CONSTRAINT `shelfcontents_ibfk_3` FOREIGN KEY (`borrowernumber`) REFERENCES `borrowers` (`borrowernumber`) ON DELETE SET NULL ON UPDATE SET NULL -- no cascaded delete, please see HandleDelBorrower in VirtualShelves.pm
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+ --
+ -- Table structure for table `virtualshelfshares`
+ --
+
+ DROP TABLE IF EXISTS `virtualshelfshares`;
+ CREATE TABLE `virtualshelfshares` ( -- shared private lists
+ `id` int AUTO_INCREMENT PRIMARY KEY, -- unique key
+ `shelfnumber` int NOT NULL, -- foreign key for virtualshelves
+ `borrowernumber` int, -- borrower that accepted access to this list
+ `invitekey` varchar(10), -- temporary string used in accepting the invitation to access thist list; not-empty means that the invitation has not been accepted yet
+ `sharedate` datetime, -- date of invitation or acceptance of invitation
+ CONSTRAINT `virtualshelfshares_ibfk_1` FOREIGN KEY (`shelfnumber`) REFERENCES `virtualshelves` (`shelfnumber`) ON DELETE CASCADE ON UPDATE CASCADE,
+ CONSTRAINT `virtualshelfshares_ibfk_2` FOREIGN KEY (`borrowernumber`) REFERENCES `borrowers` (`borrowernumber`) ON DELETE SET NULL ON UPDATE SET NULL -- no cascaded delete, please see HandleDelBorrower in VirtualShelves.pm
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
SetVersion($DBversion);
}
-
+ $DBversion = "3.07.00.029";
+ if ( C4::Context->preference("Version") < TransformToNum($DBversion) ) {
+ my $installer = C4::Installer->new();
+ my $full_path = C4::Context->config('intranetdir') . "/installer/data/$installer->{dbms}/atomicupdate/oai_sets.sql";
+ my $error = $installer->load_sql($full_path);
+ warn $error if $error;
+ print "Upgrade to $DBversion done (Atomic update for OAI-PMH sets management)\n";
+ SetVersion($DBversion);
+ }
+
+ $DBversion = "3.07.00.030";
+ if ( C4::Context->preference("Version") < TransformToNum($DBversion) ) {
+ $dbh->do("ALTER TABLE default_circ_rules ADD
+ COLUMN `returnbranch` varchar(15) default NULL AFTER `holdallowed`");
+ $dbh->do("ALTER TABLE branch_item_rules ADD
+ COLUMN `returnbranch` varchar(15) default NULL AFTER `holdallowed`");
+ $dbh->do("ALTER TABLE default_branch_circ_rules ADD
+ COLUMN `returnbranch` varchar(15) default NULL AFTER `holdallowed`");
+ $dbh->do("ALTER TABLE default_branch_item_rules ADD
+ COLUMN `returnbranch` varchar(15) default NULL AFTER `holdallowed`");
+ # set the default rule to the current value of HomeOrHoldingBranchReturn (default to 'homebranch' if need be)
+ my $homeorholdingbranchreturn = C4::Context->prefernce('HomeOrHoldingBranchReturn') || 'homebranch';
+ $dbh->do("UPDATE default_circ_rules SET returnbranch = '$homeorholdingbranchreturn'");
+ print "Upgrade to $DBversion done (Atomic update for OAI-PMH sets management)\n";
+ SetVersion($DBversion);
+ }
+
+ $DBversion = "3.07.00.031";
+ if (C4::Context->preference("Version") < TransformToNum($DBversion)) {
+ $dbh->do("INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES ('UseICU', '1', 'Tell Koha if ICU indexing is in use for Zebra or not.','1','YesNo')");
+ print "Upgrade to $DBversion done (Add syspref to tell Koha if ICU indexing is in use for Zebra or not.)\n";
+ SetVersion ($DBversion);
+ }
+
+ $DBversion = "3.07.99.032";
+ if ( C4::Context->preference("Version") lt TransformToNum($DBversion) ) {
+ $dbh->do("ALTER TABLE virtualshelves MODIFY COLUMN owner int"); #should have been int already (fk to borrowers)
+ $dbh->do("UPDATE virtualshelves vi LEFT JOIN borrowers bo ON bo.borrowernumber=vi.owner SET vi.owner=NULL where bo.borrowernumber IS NULL"); #before adding the constraint on borrowernumber, we need to get rid of deleted owners
+ $dbh->do("DELETE FROM virtualshelves WHERE owner IS NULL and category=1"); #delete private lists without owner (cascades to shelfcontents)
+ $dbh->do("ALTER TABLE virtualshelves ADD COLUMN allow_add tinyint(1) DEFAULT 0, ADD COLUMN allow_delete_own tinyint(1) DEFAULT 1, ADD COLUMN allow_delete_other tinyint(1) DEFAULT 0, ADD CONSTRAINT `virtualshelves_ibfk_1` FOREIGN KEY (`owner`) REFERENCES `borrowers` (`borrowernumber`) ON DELETE SET NULL ON UPDATE SET NULL");
+ $dbh->do("UPDATE virtualshelves SET allow_add=0, allow_delete_own=1, allow_delete_other=0 WHERE category=1");
+ $dbh->do("UPDATE virtualshelves SET allow_add=0, allow_delete_own=1, allow_delete_other=0 WHERE category=2");
+ $dbh->do("UPDATE virtualshelves SET allow_add=1, allow_delete_own=1, allow_delete_other=1 WHERE category=3");
+ $dbh->do("UPDATE virtualshelves SET category=2 WHERE category=3");
+
+ $dbh->do("ALTER TABLE virtualshelfcontents ADD COLUMN borrowernumber int, ADD CONSTRAINT `shelfcontents_ibfk_3` FOREIGN KEY (`borrowernumber`) REFERENCES `borrowers` (`borrowernumber`) ON DELETE SET NULL ON UPDATE SET NULL");
+ $dbh->do("UPDATE virtualshelfcontents co LEFT JOIN virtualshelves sh USING (shelfnumber) SET co.borrowernumber=sh.owner");
+
+ $dbh->do("CREATE TABLE virtualshelfshares
+ (id int AUTO_INCREMENT PRIMARY KEY, shelfnumber int NOT NULL,
+ borrowernumber int, invitekey varchar(10), sharedate datetime,
+ CONSTRAINT `virtualshelfshares_ibfk_1` FOREIGN KEY (`shelfnumber`) REFERENCES `virtualshelves` (`shelfnumber`) ON DELETE CASCADE ON UPDATE CASCADE,
+ CONSTRAINT `virtualshelfshares_ibfk_2` FOREIGN KEY (`borrowernumber`) REFERENCES `borrowers` (`borrowernumber`) ON DELETE SET NULL ON UPDATE SET NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8");
+
+ $dbh->do("INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('OpacAllowPublicListCreation',1,'If set, allows opac users to create public lists',NULL,'YesNo');");
+ $dbh->do("INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('OpacAllowSharingPrivateLists',0,'If set, allows opac users to share private lists with other patrons',NULL,'YesNo');");
+
+ print "Upgrade to $DBversion done (BZ7310: Improving list permissions)\n";
+ SetVersion($DBversion);
+ }
+
+$DBversion = "XXX";
+if ( C4::Context->preference("Version") < TransformToNum($DBversion) ) {
+ $dbh->do("ALTER TABLE issues CHANGE date_due date_due datetime");
+ $dbh->do("ALTER TABLE issues CHANGE returndate returndate datetime");
+ $dbh->do("ALTER TABLE issues CHANGE lastreneweddate lastreneweddate datetime");
+ $dbh->do("ALTER TABLE issues CHANGE issuedate issuedate datetime");
+ $dbh->do("ALTER TABLE old_issues CHANGE date_due date_due datetime");
+ $dbh->do("ALTER TABLE old_issues CHANGE returndate returndate datetime");
+ $dbh->do("ALTER TABLE old_issues CHANGE lastreneweddate lastreneweddate datetime");
+ $dbh->do("ALTER TABLE old_issues CHANGE issuedate issuedate datetime");
+ print "Upgrade to $DBversion done (Setting up issues tables for hourly loans)\n";
+ SetVersion($DBversion);
+}
+
-
-
=head1 FUNCTIONS
=head2 DropAllForeignKeys($table)
choices:
yes: "Don't allow"
no: Allow
- - patrons to select their branch on the OPAC.
+ - patrons to select their library on the OPAC.
-
- pref: SearchMyLibraryFirst
choices:
- Use
- pref: OpacRenewalBranch
choices:
- itemhomebranch: "the item's home branch"
- patronhomebranch: "the patron's home branch"
- checkoutbranch: "the branch the item was checked out from"
+ itemhomebranch: "the item's home library"
+ patronhomebranch: "the patron's home library"
+ checkoutbranch: "the library the item was checked out from"
null: "NULL"
opacrenew: "'OPACRenew'"
- as branchcode to store in the statistics table.
- Only allow patrons to renew their own books on the OPAC if they have less than
- pref: OPACFineNoRenewals
class: currency
- - '[% local_currency %] in fines (set a large value to always allow renewal).'
+ - '[% local_currency %] in fines (leave blank to disable).'
-
- pref: OPACViewOthersSuggestions
choices:
choices:
no: "Don't allow"
yes: Allow
- - patrons to select branch when making a purchase suggestion
+ - patrons to select library when making a purchase suggestion
-
- pref: OpacHiddenItems
type: textarea
class: code
- - Allows to define custom rules for hiding specific items at opac. See docs/opac/OpacHiddenItems.txt for more informations.
+ - Allows to define custom rules for hiding specific items at opac. See docs/opac/OpacHiddenItems.txt for more informations
+ -
+ - pref: OpacAllowPublicListCreation
+ default: 1
+ choices:
+ no: "Don't allow"
+ yes: Allow
+ - opac users to create public lists
+ -
+ - pref: OpacAllowSharingPrivateLists
+ default: 0
+ choices:
+ no: "Don't allow"
+ yes: Allow
+ - opac users to share private lists with other patrons. This feature is not active yet but will be released soon
Privacy:
-
choices:
yes: Use
no: "Don't use"
- - "the item home branch when finding items for the shelf browser."
+ - "the item home library when finding items for the shelf browser."
-
- pref: ShelfBrowserUsesCcode
default: 0
<input type="hidden" name="op" value="add" />
<table>
<tr>
- <th>Patron Category</th>
- <th>Item Type</th>
- <th>Current Checkouts Allowed</th>
- <th>Loan Period</th>
+ <th>Patron category</th>
+ <th>Item type</th>
+ <th>Current checkouts allowed</th>
- <th>Loan period (day)</th>
++ <th>Loan period</th>
+ <th>Unit</th>
- <th>Hard Due Date</th>
- <th>Fine Amount</th>
- <th>Fine Charging Interval</th>
- <th>Fine Grace period (day)</th>
- <th>Suspension in Days (day)</th>
- <th>Renewals Allowed (count)</th>
- <th>Holds Allowed (count)</th>
- <th>Rental Discount (%)</th>
+ <th>Hard due date</th>
+ <th>Fine amount</th>
+ <th>Fine charging interval</th>
+ <th>Fine grace period (day)</th>
+ <th>Suspension in days (day)</th>
+ <th>Renewals allowed (count)</th>
+ <th>Holds allowed (count)</th>
- <th>Rental discount (%)</th>
++ <th>Rental discount (%)</th>
<th> </th>
</tr>
[% FOREACH rule IN rules %]
[% END %]
</td>
<td>[% rule.issuelength %]</td>
+ <td>
+ [% rule.lengthunit %]
+ </td>
<td>[% IF ( rule.hardduedate ) %]
[% IF ( rule.hardduedatebefore ) %]before [% rule.hardduedate %]</td>
[% ELSE %][% IF ( rule.hardduedateexact ) %]on [% rule.hardduedate %]</td>
</td>
<td><input name="maxissueqty" size="3" /></td>
<td><input name="issuelength" size="3" /> </td>
+ <td>
+ <select name="lengthunit">
+ <option value="days" selected>Days</option>
+ <option value="hours">Hours</option>
+ </select>
+ </td>
<td><select name="hardduedatecompare">
<option value="-1">Before</option>
<option value="0">Exactly on</option>
</form>
</div>
<div id="defaults-for-this-library" class="container">
- <h3>Default checkout and hold policy for [% IF ( humanbranch ) %][% humanbranch %][% ELSE %]all libraries[% END %]</h3>
- <p>You can set a default maximum number of checkouts and hold policy that will be used if none is defined below for a particular item type or category.</p>
+ <h3>Default checkout, hold and return policy for [% IF ( humanbranch ) %][% humanbranch %][% ELSE %]all libraries[% END %]</h3>
+ <p>You can set a default maximum number of checkouts, hold policy and return policy that will be used if none is defined below for a particular item type or category.</p>
<form method="post" action="/cgi-bin/koha/admin/smart-rules.pl">
<input type="hidden" name="op" value="set-branch-defaults" />
<input type="hidden" name="branch" value="[% current_branch %]"/>
<table>
<tr>
<th> </th>
- <th>Total Current Checkouts Allowed</th>
- <th>Hold Policy</th>
+ <th>Total current checkouts allowed</th>
+ <th>Hold policy</th>
+ <th>Return policy</th>
<th> </th>
<th> </th>
</tr>
[% ELSE %]
<option value="2">
[% END %]
- From Any Library
+ From any library
</option>
[% IF ( default_holdallowed_same ) %]
<option value="1" selected="selected">
[% ELSE %]
<option value="1">
[% END %]
- From Home Library
+ From home library
</option>
[% IF ( default_holdallowed_none ) %]
<option value="0" selected="selected">
[% ELSE %]
<option value="0">
[% END %]
- No Holds Allowed
+ No holds allowed
+ </option>
+ </select>
+ </td>
+ <td>
+ <select name="returnbranch">
+ [% IF ( default_returnbranch == 'homebranch' ) %]
+ <option value="homebranch" selected="selected">
+ [% ELSE %]
+ <option value="homebranch">
+ [% END %]
+ Item returns home
+ </option>
+ [% IF ( default_returnbranch == 'holdingbranch' ) %]
+ <option value="holdingbranch" selected="selected">
+ [% ELSE %]
+ <option value="holdingbranch">
+ [% END %]
+ Item returns to issuing branch
+ </option>
+ [% IF ( default_returnbranch == 'noreturn' ) %]
+ <option value="noreturn" selected="selected">
+ [% ELSE %]
+ <option value="noreturn">
+ [% END %]
+ Item floats
</option>
</select>
</td>
<input type="hidden" name="branch" value="[% current_branch %]"/>
<table>
<tr>
- <th>Patron Category</th>
- <th>Total Current Checkouts Allowed</th>
+ <th>Patron category</th>
+ <th>Total current checkouts allowed</th>
<th> </th>
</tr>
[% FOREACH branch_cat_rule_loo IN branch_cat_rule_loop %]
The various policies have the following effects:
</p>
<ul>
- <li><strong>From Any Library:</strong> Patrons from any library may put this item on hold. <cite>(default if none is defined)</cite></li>
- <li><strong>From Home Library:</strong> Only patrons from the item's home library may put this book on hold.</li>
- <li><strong>No Holds Allowed:</strong> No patron may put this book on hold.</li>
+ <li><strong>From any library:</strong> Patrons from any library may put this item on hold. <cite>(default if none is defined)</cite></li>
+ <li><strong>From home library:</strong> Only patrons from the item's home library may put this book on hold.</li>
+ <li><strong>No holds allowed:</strong> No patron may put this book on hold.</li>
</ul>
<p>
Note that if the system preference
<input type="hidden" name="branch" value="[% current_branch %]"/>
<table>
<tr>
- <th>Item Type</th>
- <th>Hold Policy</th>
+ <th>Item type</th>
+ <th>Hold policy</th>
+ <th>Return policy</th>
<th> </th>
</tr>
[% FOREACH branch_item_rule_loo IN branch_item_rule_loop %]
[% END %]
</td>
<td>[% IF ( branch_item_rule_loo.holdallowed_any ) %]
- From Any Library
+ From any library
[% ELSIF ( branch_item_rule_loo.holdallowed_same ) %]
- From Home Library
+ From home library
[% ELSE %]
- No Holds Allowed
+ No holds allowed
+ [% END %]
+ </td>
+ <td>[% IF ( branch_item_rule_loo.returnbranch == 'homebranch' ) %]
+ Item returns home
+ [% ELSIF ( branch_item_rule_loo.returnbranch == 'holdingbranch' ) %]
+ Item returns to issuing branch
+ [% ELSIF ( branch_item_rule_loo.returnbranch == 'noreturn' ) %]
+ Item floats
+ [% ELSE %]
+ Error - unknown option
[% END %]
</td>
<td>
</td>
<td>
<select name="holdallowed">
- <option value="2">From Any Library</option>
- <option value="1">From Home Library</option>
- <option value="0">No Holds Allowed</option>
+ <option value="2">From any library</option>
+ <option value="1">From home library</option>
+ <option value="0">No holds allowed</option>
+ </select>
+ </td>
+ <td>
+ <select name="returnbranch">
+ <option value="homebranch">Item returns home</option>
+ <option value="holdingbranch">Item returns to issuing branch</option>
+ <option value="noreturn">Item floats</option>
</select>
</td>
<td><input type="submit" value="Add" class="submit" /></td>
+[% USE KohaDates %]
[% INCLUDE 'doc-head-open.inc' %]
<title>Koha › Circulation › Check In [% title |html %]</title>
[% INCLUDE 'doc-head-close.inc' %]
[% END %]
[% IF ( transfer ) %]
- <!-- transfer: item with no reservation, must be returned to its homebranch -->
+ <!-- transfer: item with no reservation, must be returned to its home library -->
<div id="return1" class="dialog message">
<h3>Please return <a href="/cgi-bin/koha/catalogue/detail.pl?type=intra&biblionumber=[% itembiblionumber %]">[% title or "item" |html %]</a> to [% homebranchname %]<br/>( <a href="#" onclick="Dopop('transfer-slip.pl?transferitem=[% itemnumber %]&branchcode=[% homebranch %]&op=slip'); return true;">Print Slip</a> )</h3>
</div>
<p class="problem">Item is withdrawn.</p>
[% END %]
[% IF ( errmsgloo.debarred ) %]
- <p class="problem"><a href="/cgi-bin/koha/circ/circulation.pl?borrowernumber=[% errmsgloo.debarborrowernumber %]">[% errmsgloo.debarname %]([% errmsgloo.debarcardnumber %])</a> is now debarred until [% errmsgloo.debarred %] </p>
+ <p class="problem"><a href="/cgi-bin/koha/circ/circulation.pl?borrowernumber=[% errmsgloo.debarborrowernumber %]">[% errmsgloo.debarname %]([% errmsgloo.debarcardnumber %])</a> is now debarred until [% errmsgloo.debarred | $KohaDates %] </p>
[% END %]
[% END %]
[% IF ( soundon ) %]
use C4::Branch; # GetBranches
use C4::Overdues;
use C4::Debug;
+use Koha::DateUtils;
# use Data::Dumper;
my $MAXIMUM_NUMBER_OF_RESERVES = C4::Context->preference("maxreserves");
my $itemNum = shift(@selectedItems);
my $branch = shift(@selectedItems); # i.e., branch code, not name
- my $singleBranchMode = $template->param('singleBranchMode');
+ my $singleBranchMode = C4::Context->preference("singleBranchMode");
if ($singleBranchMode || ! $OPACChooseBranch) { # single branch mode or disabled user choosing
$branch = $borr->{'branchcode'};
}
# change the background color.
my $issues= GetItemIssue($itemNum);
if ( $issues->{'date_due'} ) {
- $itemLoopIter->{dateDue} = format_date($issues->{'date_due'});
+ $itemLoopIter->{dateDue} = format_sqlduedatetime($issues->{date_due});
$itemLoopIter->{backgroundcolor} = 'onloan';
}
use C4::Dates qw/format_date/;
use C4::Letters;
use C4::Branch; # GetBranches
+use Koha::DateUtils;
use constant ATTRIBUTE_SHOW_BARCODE => 'SHOW_BCODE';
my @overdues;
my @issuedat;
my $itemtypes = GetItemTypes();
-my ($issues) = GetPendingIssues($borrowernumber);
+my $issues = GetPendingIssues($borrowernumber);
if ($issues){
- foreach my $issue ( sort { $b->{'date_due'} cmp $a->{'date_due'} } @$issues ) {
+ foreach my $issue ( sort { $b->{date_due}->datetime() cmp $a->{date_due}->datetime() } @{$issues} ) {
# check for reserves
my ( $restype, $res, undef ) = CheckReserves( $issue->{'itemnumber'} );
if ( $restype ) {
$issue->{'imageurl'} = getitemtypeimagelocation( 'opac', $itemtypes->{$itemtype}->{'imageurl'} );
$issue->{'description'} = $itemtypes->{$itemtype}->{'description'};
}
- $issue->{date_due} = format_date($issue->{date_due});
+ $issue->{date_due} = output_pref_due($issue->{date_due});
push @issuedat, $issue;
$count++;
$template->param(
bor_messages_loop => GetMessages( $borrowernumber, 'B', 'NONE' ),
waiting_count => $wcount,
- textmessaging => $borr->{textmessaging},
patronupdate => $patronupdate,
OpacRenewalAllowed => C4::Context->preference("OpacRenewalAllowed"),
userview => 1,