X-Git-Url: http://koha-dev.rot13.org:8081/gitweb/?a=blobdiff_plain;f=C4%2FCirculation.pm;h=e64f07d79e441c5b98a17a7471c956d2f23c3d0c;hb=cec20df6d9a863d9ee33c670970b37f62d508280;hp=49bd7b2e827c07d37ca738a9021a2ba5c6150705;hpb=7a8bed557618e26f867a74f53c1391c12acfb77a;p=koha_fer diff --git a/C4/Circulation.pm b/C4/Circulation.pm index 49bd7b2e82..e64f07d79e 100644 --- a/C4/Circulation.pm +++ b/C4/Circulation.pm @@ -36,17 +36,28 @@ use C4::Message; use C4::Debug; use C4::Branch; # GetBranches use C4::Log; # logaction +use C4::Koha qw(GetAuthorisedValueByCode); +use C4::Overdues qw(CalcFine UpdateFine); +use Algorithm::CheckDigits; use Data::Dumper; use Koha::DateUtils; use Koha::Calendar; use Carp; - +use Date::Calc qw( + Today + Today_and_Now + Add_Delta_YM + Add_Delta_DHMS + Date_to_Days + Day_of_Week + Add_Delta_Days +); use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS); BEGIN { require Exporter; - $VERSION = 3.02; # for version checking + $VERSION = 3.07.00.049; # for version checking @ISA = qw(Exporter); # FIXME subs that should probably be elsewhere @@ -168,6 +179,14 @@ sub barcodedecode { $barcode =~ s/^(\D+)[0]*(\d+)$/$branch-$1-$2/i; } } + } elsif ($filter eq 'EAN13') { + my $ean = CheckDigits('ean'); + if ( $ean->is_valid($barcode) ) { + #$barcode = sprintf('%013d',$barcode); # this doesn't work on 32-bit systems + $barcode = '0' x ( 13 - length($barcode) ) . $barcode; + } else { + warn "# [$barcode] not valid EAN-13/UPC-A\n"; + } } return $barcode; # return barcode, modified or not } @@ -667,6 +686,8 @@ sub CanBookBeIssued { my ( $borrower, $barcode, $duedate, $inprocess, $ignore_reserves ) = @_; my %needsconfirmation; # filled with problems that needs confirmations my %issuingimpossible; # filled with problems that causes the issue to be IMPOSSIBLE + my %alerts; # filled with messages that shouldn't stop issuing, but the librarian should be aware of. + my $item = GetItem(GetItemnumberFromBarcode( $barcode )); my $issue = GetItemIssue($item->{itemnumber}); my $biblioitem = GetBiblioItemData($item->{biblioitemnumber}); @@ -698,7 +719,7 @@ sub CanBookBeIssued { } if ($duedate) { my $today = $now->clone(); - $today->truncate( to => 'minutes'); + $today->truncate( to => 'minute'); if (DateTime->compare($duedate,$today) == -1 ) { # duedate cannot be before now $needsconfirmation{INVALID_DATE} = output_pref($duedate); } @@ -711,7 +732,7 @@ sub CanBookBeIssued { # if ( $borrower->{'category_type'} eq 'X' && ( $item->{barcode} )) { # stats only borrower -- add entry to statistics table, and return issuingimpossible{STATS} = 1 . - &UpdateStats(C4::Context->userenv->{'branch'},'localuse','','',$item->{'itemnumber'},$item->{'itemtype'},$borrower->{'borrowernumber'}); + &UpdateStats(C4::Context->userenv->{'branch'},'localuse','','',$item->{'itemnumber'},$item->{'itemtype'},$borrower->{'borrowernumber'}, undef, $item->{'ccode'}); ModDateLastSeen( $item->{'itemnumber'} ); return( { STATS => 1 }, {}); } @@ -735,8 +756,8 @@ sub CanBookBeIssued { day => $d, time_zone => C4::Context->tz, ); - $expiry_dt->truncate( to => 'days'); - my $today = $now->clone()->truncate(to => 'days'); + $expiry_dt->truncate( to => 'day'); + my $today = $now->clone()->truncate(to => 'day'); if (DateTime->compare($today, $expiry_dt) == 1) { $issuingimpossible{EXPIRED} = 1; } @@ -848,6 +869,11 @@ sub CanBookBeIssued { { $issuingimpossible{RESTRICTED} = 1; } + if ( $item->{'itemlost'} && C4::Context->preference("IssueLostItem") ne 'nothing' ) { + my $code = GetAuthorisedValueByCode( 'LOST', $item->{'itemlost'} ); + $needsconfirmation{ITEM_LOST} = $code if ( C4::Context->preference("IssueLostItem") eq 'confirm' ); + $alerts{ITEM_LOST} = $code if ( C4::Context->preference("IssueLostItem") eq 'alert' ); + } if ( C4::Context->preference("IndependantBranches") ) { my $userenv = C4::Context->userenv; if ( ($userenv) && ( $userenv->{flags} % 2 != 1 ) ) { @@ -923,7 +949,63 @@ sub CanBookBeIssued { } } } - return ( \%issuingimpossible, \%needsconfirmation ); + # + # CHECK AGE RESTRICTION + # + + # get $marker from preferences. Could be something like "FSK|PEGI|Alter|Age:" + my $markers = C4::Context->preference('AgeRestrictionMarker' ); + my $bibvalues = $biblioitem->{'agerestriction'}; + if (($markers)&&($bibvalues)) + { + # Split $bibvalues to something like FSK 16 or PEGI 6 + my @values = split ' ', $bibvalues; + + # Search first occurence of one of the markers + my @markers = split /\|/, $markers; + my $index = 0; + my $take = -1; + for my $value (@values) { + $index ++; + for my $marker (@markers) { + $marker =~ s/^\s+//; #remove leading spaces + $marker =~ s/\s+$//; #remove trailing spaces + if (uc($marker) eq uc($value)) { + $take = $index; + last; + } + } + if ($take > -1) { + last; + } + } + # Index points to the next value + my $restrictionyear = 0; + if (($take <= $#values) && ($take >= 0)){ + $restrictionyear += $values[$take]; + } + + if ($restrictionyear > 0) { + if ( $borrower->{'dateofbirth'} ) { + my @alloweddate = split /-/,$borrower->{'dateofbirth'} ; + $alloweddate[0] += $restrictionyear; + #Prevent runime eror on leap year (invalid date) + if (($alloweddate[1] == 2) && ($alloweddate[2] == 29)) { + $alloweddate[2] = 28; + } + + if ( Date_to_Days(Today) < Date_to_Days(@alloweddate) -1 ) { + if (C4::Context->preference('AgeRestrictionOverride' )) { + $needsconfirmation{AGE_RESTRICTION} = "$bibvalues"; + } + else { + $issuingimpossible{AGE_RESTRICTION} = "$bibvalues"; + } + } + } + } + } + return ( \%issuingimpossible, \%needsconfirmation, \%alerts ); } =head2 AddIssue @@ -996,12 +1078,12 @@ sub AddIssue { # 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 { @@ -1016,7 +1098,6 @@ sub AddIssue { } 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) { @@ -1044,7 +1125,7 @@ sub AddIssue { $datedue = CalcDateDue( $issuedate, $itype, $branch, $borrower ); } - $datedue->truncate( to => 'minutes'); + $datedue->truncate( to => 'minute'); $sth->execute( $borrower->{'borrowernumber'}, # borrowernumber $item->{'itemnumber'}, # itemnumber @@ -1056,6 +1137,9 @@ sub AddIssue { CartToShelf( $item->{'itemnumber'} ); } $item->{'issues'}++; + if ( C4::Context->preference('UpdateTotalIssuesOnCirc') ) { + UpdateTotalIssues($item->{'biblionumber'}, 1); + } ## If item was lost, it has now been found, reverse any list item charges if neccessary. if ( $item->{'itemlost'} ) { @@ -1088,7 +1172,7 @@ sub AddIssue { C4::Context->userenv->{'branch'}, 'issue', $charge, ($sipmode ? "SIP-$sipmode" : ''), $item->{'itemnumber'}, - $item->{'itype'}, $borrower->{'borrowernumber'} + $item->{'itype'}, $borrower->{'borrowernumber'}, undef, $item->{'ccode'} ); # Send a checkout slip. @@ -1192,53 +1276,16 @@ Get the Hard Due Date and it's comparison for an itemtype, a borrower type and a sub GetHardDueDate { my ( $borrowertype, $itemtype, $branchcode ) = @_; - my $dbh = C4::Context->dbh; - my $sth = - $dbh->prepare( -"select hardduedate, hardduedatecompare from issuingrules where categorycode=? and itemtype=? and branchcode=?" - ); - $sth->execute( $borrowertype, $itemtype, $branchcode ); - my $results = $sth->fetchrow_hashref; - return (dt_from_string($results->{hardduedate}, 'iso'),$results->{hardduedatecompare}) - if defined($results) && $results->{hardduedate}; - - $sth->execute( $borrowertype, "*", $branchcode ); - $results = $sth->fetchrow_hashref; - return (dt_from_string($results->{hardduedate}, 'iso'),$results->{hardduedatecompare}) - if defined($results) && $results->{hardduedate}; - $sth->execute( "*", $itemtype, $branchcode ); - $results = $sth->fetchrow_hashref; - return (dt_from_string($results->{hardduedate}, 'iso'),$results->{hardduedatecompare}) - if defined($results) && $results->{hardduedate}; - - $sth->execute( "*", "*", $branchcode ); - $results = $sth->fetchrow_hashref; - return (dt_from_string($results->{hardduedate}, 'iso'),$results->{hardduedatecompare}) - if defined($results) && $results->{hardduedate}; + my $rule = GetIssuingRule( $borrowertype, $itemtype, $branchcode ); - $sth->execute( $borrowertype, $itemtype, "*" ); - $results = $sth->fetchrow_hashref; - return (dt_from_string($results->{hardduedate}, 'iso'),$results->{hardduedatecompare}) - if defined($results) && $results->{hardduedate}; - - $sth->execute( $borrowertype, "*", "*" ); - $results = $sth->fetchrow_hashref; - return (dt_from_string($results->{hardduedate}, 'iso'),$results->{hardduedatecompare}) - if defined($results) && $results->{hardduedate}; - - $sth->execute( "*", $itemtype, "*" ); - $results = $sth->fetchrow_hashref; - return (dt_from_string($results->{hardduedate}, 'iso'),$results->{hardduedatecompare}) - if defined($results) && $results->{hardduedate}; - - $sth->execute( "*", "*", "*" ); - $results = $sth->fetchrow_hashref; - return (dt_from_string($results->{hardduedate}, 'iso'),$results->{hardduedatecompare}) - if defined($results) && $results->{hardduedate}; - - # if no rule is set => return undefined - return (undef, undef); + if ( defined( $rule ) ) { + if ( $rule->{hardduedate} ) { + return (dt_from_string($rule->{hardduedate}, 'iso'),$rule->{hardduedatecompare}); + } else { + return (undef, undef); + } + } } =head2 GetIssuingRule @@ -1386,13 +1433,17 @@ sub GetBranchBorrowerCircRule { 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 @@ -1400,7 +1451,7 @@ This searches branchitemrules in the following order: * branchcode '*', same itemtype * branchcode and itemtype '*' -Neither C<$branchcode> nor C<$categorycode> should be '*'. +Neither C<$branchcode> nor C<$itemtype> should be '*'. =cut @@ -1410,33 +1461,37 @@ sub GetBranchItemRule { 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 ) + or next; # 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 @@ -1515,6 +1570,7 @@ patron who last borrowed the book. sub AddReturn { my ( $barcode, $branch, $exemptfine, $dropbox ) = @_; + if ($branch and not GetBranchDetail($branch)) { warn "AddReturn error: branch '$branch' not found. Reverting to " . C4::Context->userenv->{'branch'}; undef $branch; @@ -1553,9 +1609,10 @@ sub 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 @@ -1566,8 +1623,8 @@ sub AddReturn { $branches->{$hbr}->{PE} and $messages->{'IsPermanent'} = $hbr; } - # if indy branches and returning to different branch, refuse the return - if ($hbr ne $branch && C4::Context->preference("IndependantBranches")){ + # if indy branches and returning to different branch, refuse the return unless canreservefromotherbranches is turned on + if ($hbr ne $branch && C4::Context->preference("IndependantBranches") && !(C4::Context->preference("canreservefromotherbranches"))){ $messages->{'Wrongbranch'} = { Wrongbranch => $branch, Rightbranch => $hbr, @@ -1587,7 +1644,9 @@ sub AddReturn { } # case of a return of document (deal with issues and holdingbranch) + my $today = DateTime->now( time_zone => C4::Context->tz() ); if ($doreturn) { + my $datedue = $issue->{date_due}; $borrower or warn "AddReturn without current borrower"; my $circControlBranch; if ($dropbox) { @@ -1596,9 +1655,21 @@ sub AddReturn { # FIXME: check issuedate > returndate, factoring in holidays #$circControlBranch = _GetCircControlBranch($item,$borrower) unless ( $item->{'issuedate'} eq C4::Dates->today('iso') );; $circControlBranch = _GetCircControlBranch($item,$borrower); + $issue->{'overdue'} = DateTime->compare($issue->{'date_due'}, $today ) == -1 ? 1 : 0; } if ($borrowernumber) { + if($issue->{'overdue'}){ + my ( $amount, $type, $unitcounttotal ) = C4::Overdues::CalcFine( $item, $borrower->{categorycode},$branch, $datedue, $today ); + $type ||= q{}; + if ( $amount > 0 && ( C4::Context->preference('finesMode') eq 'production' )) { + C4::Overdues::UpdateFine( + $issue->{itemnumber}, + $issue->{borrowernumber}, + $amount, $type, output_pref($datedue) + ); + } + } MarkIssueReturned($borrowernumber, $item->{'itemnumber'}, $circControlBranch, '', $borrower->{'privacy'}); $messages->{'WasReturned'} = 1; # FIXME is the "= 1" right? This could be the borrower hash. } @@ -1625,12 +1696,15 @@ sub AddReturn { ); $sth->execute( $item->{'itemnumber'} ); # if we have a reservation with valid transfer, we can set it's status to 'W' + ShelfToCart( $item->{'itemnumber'} ) if ( C4::Context->preference("ReturnToShelvingCart") ); C4::Reserves::ModReserveStatus($item->{'itemnumber'}, 'W'); } else { $messages->{'WrongTransfer'} = $tobranch; $messages->{'WrongTransferItem'} = $item->{'itemnumber'}; } $validTransfert = 1; + } else { + ShelfToCart( $item->{'itemnumber'} ) if ( C4::Context->preference("ReturnToShelvingCart") ); } # fix up the accounts..... @@ -1644,9 +1718,12 @@ sub AddReturn { my $fix = _FixOverduesOnReturn($borrowernumber, $item->{itemnumber}, $exemptfine, $dropbox); defined($fix) or warn "_FixOverduesOnReturn($borrowernumber, $item->{itemnumber}...) failed!"; # zero is OK, check defined - # fix fine days - my $debardate = _FixFineDaysOnReturn( $borrower, $item, $issue->{date_due} ); - $messages->{'Debarred'} = $debardate if ($debardate); + if ( $issue->{overdue} && $issue->{date_due} ) { +# fix fine days + my $debardate = + _debar_user_on_return( $borrower, $item, $issue->{date_due}, $today ); + $messages->{Debarred} = $debardate if ($debardate); + } } # find reserves..... @@ -1663,7 +1740,7 @@ sub AddReturn { $branch, $stat_type, '0', '', $item->{'itemnumber'}, $biblio->{'itemtype'}, - $borrowernumber + $borrowernumber, undef, $item->{'ccode'} ); # Send a check-in slip. # NOTE: borrower may be undef. probably shouldn't try to send messages then. @@ -1731,14 +1808,15 @@ routine in C. sub MarkIssueReturned { my ( $borrowernumber, $itemnumber, $dropbox_branch, $returndate, $privacy ) = @_; + my $dbh = C4::Context->dbh; my $query = 'UPDATE issues SET returndate='; my @bind; if ($dropbox_branch) { - my $calendar = Koha->new( branchcode => $dropbox_branch ); + my $calendar = Koha::Calendar->new( branchcode => $dropbox_branch ); my $dropboxdate = $calendar->addDate( DateTime->now( time_zone => C4::Context->tz), -1 ); $query .= ' ? '; - push @bind, $dropboxdate->strftimei('%Y-%m-%d %H:%M'); + push @bind, $dropboxdate->strftime('%Y-%m-%d %H:%M'); } elsif ($returndate) { $query .= ' ? '; push @bind, $returndate; @@ -1770,59 +1848,70 @@ sub MarkIssueReturned { $sth_del->execute($borrowernumber, $itemnumber); } -=head2 _FixFineDaysOnReturn +=head2 _debar_user_on_return - &_FixFineDaysOnReturn($borrower, $item, $datedue); + _debar_user_on_return($borrower, $item, $datedue, today); C<$borrower> borrower hashref C<$item> item hashref -C<$datedue> date due +C<$datedue> date due DateTime object -Internal function, called only by AddReturn that calculate and update the user fine days, and debars him +C<$today> DateTime object representing the return time -=cut +Internal function, called only by AddReturn that calculates and updates + the user fine days, and debars him if necessary. -sub _FixFineDaysOnReturn { - my ( $borrower, $item, $datedue ) = @_; +Should only be called for overdue returns - if ($datedue) { - $datedue = C4::Dates->new( $datedue, "iso" ); - } else { - return; - } +=cut + +sub _debar_user_on_return { + my ( $borrower, $item, $dt_due, $dt_today ) = @_; 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 ); - my $finedays = $issuingrule->{finedays}; - - # 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 $issuingrule = + GetIssuingRule( $borrower->{categorycode}, $item->{itype}, $branchcode ); + my $finedays = $issuingrule->{finedays}; + my $unit = $issuingrule->{lengthunit}; + + if ($finedays) { + + # 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' ); + + # grace period is measured in the same units as the loan + my $grace = + DateTime::Duration->new( $unit => $issuingrule->{firstremind} ); + if ( $deltadays->subtract($grace)->is_positive() ) { + + my $new_debar_dt = + $dt_today->clone()->add_duration( $deltadays * $finedays ); + if ( $borrower->{debarred} ) { + my $borrower_debar_dt = dt_from_string( $borrower->{debarred} ); + + # Update patron only if new date > old + if ( DateTime->compare( $borrower_debar_dt, $new_debar_dt ) != + -1 ) + { + return; + } + } - } else { - C4::Members::DebarMember( $borrower->{borrowernumber}, $isonewdate ); - return $isonewdate; + C4::Members::DebarMember( $borrower->{borrowernumber}, + $new_debar_dt->ymd() ); + return $new_debar_dt->ymd(); } } + return; } =head2 _FixOverduesOnReturn @@ -2045,10 +2134,10 @@ sub GetItemIssue { my $data = $sth->fetchrow_hashref; return unless $data; $data->{issuedate} = dt_from_string($data->{issuedate}, 'sql'); - $data->{issuedate}->truncate(to => 'minutes'); + $data->{issuedate}->truncate(to => 'minute'); $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->{date_due}->truncate(to => 'minute'); + my $dt = DateTime->now( time_zone => C4::Context->tz)->truncate( to => 'minute'); $data->{'overdue'} = DateTime->compare($data->{'date_due'}, $dt ) == -1 ? 1 : 0; return $data; } @@ -2093,7 +2182,7 @@ sub GetItemIssues { my ( $itemnumber, $history ) = @_; my $today = DateTime->now( time_zome => C4::Context->tz); # get today date - $today->truncate( to => 'minutes' ); + $today->truncate( to => 'minute' ); my $sql = "SELECT * FROM issues JOIN borrowers USING (borrowernumber) JOIN items USING (itemnumber) @@ -2115,7 +2204,7 @@ sub GetItemIssues { my $results = $sth->fetchall_arrayref({}); foreach (@$results) { my $date_due = dt_from_string($_->{date_due},'sql'); - $date_due->truncate( to => 'minutes' ); + $date_due->truncate( to => 'minute' ); $_->{overdue} = (DateTime->compare($date_due, $today) == -1) ? 1 : 0; } @@ -2383,7 +2472,7 @@ sub AddRenewal { 'Rent', $charge, $itemnumber ); } # Log the renewal - UpdateStats( $branch, 'renew', $charge, '', $itemnumber, $item->{itype}, $borrowernumber); + UpdateStats( $branch, 'renew', $charge, '', $itemnumber, $item->{itype}, $borrowernumber, undef, $item->{'ccode'}); return $datedue; } @@ -2708,11 +2797,14 @@ sub SendCirculationAlert { borrowernumber => $borrower->{borrowernumber}, message_name => $message_name{$type}, }); + my $issues_table = ( $type eq 'CHECKOUT' ) ? 'issues' : 'old_issues'; my $letter = C4::Letters::GetPreparedLetter ( module => 'circulation', letter_code => $type, branchcode => $branch, tables => { + $issues_table => $item->{itemnumber}, + 'items' => $item->{itemnumber}, 'biblio' => $item->{biblionumber}, 'biblioitems' => $item->{biblionumber}, 'borrowers' => $borrower, @@ -2720,7 +2812,7 @@ sub SendCirculationAlert { } ) or return; - my @transports = @{ $borrower_preferences->{transports} }; + my @transports = keys %{ $borrower_preferences->{transports} }; # warn "no transports" unless @transports; for (@transports) { # warn "transport: $_"; @@ -3046,10 +3138,12 @@ sub ReturnLostItem{ MarkIssueReturned( $borrowernumber, $itemnum ); my $borrower = C4::Members::GetMember( 'borrowernumber'=>$borrowernumber ); + my $item = C4::Items::GetItem( $itemnum ); + my $old_note = ($item->{'paidfor'} && ($item->{'paidfor'} ne q{})) ? $item->{'paidfor'}.' / ' : q{}; my @datearr = localtime(time); my $date = ( 1900 + $datearr[5] ) . "-" . ( $datearr[4] + 1 ) . "-" . $datearr[3]; my $bor = "$borrower->{'firstname'} $borrower->{'surname'} $borrower->{'cardnumber'}"; - ModItem({ paidfor => "Paid for by $bor $date" }, undef, $itemnum); + ModItem({ paidfor => $old_note."Paid for by $bor $date" }, undef, $itemnum); } @@ -3068,12 +3162,13 @@ sub LostItem{ # if a borrower lost the item, add a replacement cost to the their record if ( my $borrowernumber = $issues->{borrowernumber} ){ + my $borrower = C4::Members::GetMemberDetails( $borrowernumber ); C4::Accounts::chargelostitem($borrowernumber, $itemnumber, $issues->{'replacementprice'}, "Lost Item $issues->{'title'} $issues->{'barcode'}") if $charge_fee; #FIXME : Should probably have a way to distinguish this from an item that really was returned. #warn " $issues->{'borrowernumber'} / $itemnumber "; - MarkIssueReturned($borrowernumber,$itemnumber) if $mark_returned; + MarkIssueReturned($borrowernumber,$itemnumber,undef,undef,$borrower->{'privacy'}) if $mark_returned; } }