X-Git-Url: http://koha-dev.rot13.org:8081/gitweb/?a=blobdiff_plain;f=C4%2FCirculation.pm;h=8bd53b9f54c265762b151d875ccaa60f1c70be64;hb=0d4acbba5c5db238eb42ed37dc9ba3dc2f36974b;hp=c26de760c0fd6eee971265a0cd14c43670a886f9;hpb=66350848b68e64af64bc0778b8ea0ac5ef115381;p=srvgit diff --git a/C4/Circulation.pm b/C4/Circulation.pm index c26de760c0..8bd53b9f54 100644 --- a/C4/Circulation.pm +++ b/C4/Circulation.pm @@ -38,16 +38,26 @@ 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 @@ -169,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 } @@ -668,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}); @@ -699,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); } @@ -736,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; } @@ -849,8 +869,10 @@ sub CanBookBeIssued { { $issuingimpossible{RESTRICTED} = 1; } - if ( $item->{'itemlost'} ) { - $needsconfirmation{ITEM_LOST} = GetAuthorisedValueByCode( 'LOST', $item->{'itemlost'} ); + 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; @@ -927,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 @@ -1047,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 @@ -1059,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'} ) { @@ -1195,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 @@ -1525,6 +1569,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; @@ -1615,7 +1660,7 @@ sub AddReturn { if ($borrowernumber) { if($issue->{'overdue'}){ - my ( $amount, $type, $daycounttotal ) = C4::Overdues::CalcFine( $item, $borrower->{categorycode},$branch, $datedue, $today ); + 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( @@ -1651,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..... @@ -1757,6 +1805,7 @@ 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; @@ -2075,10 +2124,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; } @@ -2123,7 +2172,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) @@ -2145,7 +2194,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; } @@ -2738,11 +2787,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, @@ -2750,7 +2802,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: $_"; @@ -3076,10 +3128,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); } @@ -3098,12 +3152,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; } }