X-Git-Url: http://koha-dev.rot13.org:8081/gitweb/?a=blobdiff_plain;f=C4%2FCirculation.pm;h=b6e86e0d45aedab5ed188a6792c2c4f614a43d06;hb=9e11576caa87e40456255e727df4379ec799f672;hp=2bf5d519a0454ee892c44c7a8cdd55b4fa441805;hpb=6b092f0e2784c3ea82f48fe8a6660d54a3fe6119;p=koha_gimpoz diff --git a/C4/Circulation.pm b/C4/Circulation.pm index 2bf5d519a0..b6e86e0d45 100644 --- a/C4/Circulation.pm +++ b/C4/Circulation.pm @@ -99,7 +99,17 @@ BEGIN { &IsBranchTransferAllowed &CreateBranchTransferLimit &DeleteBranchTransferLimits + &TransferSlip ); + + # subs to deal with offline circulation + push @EXPORT, qw( + &GetOfflineOperations + &GetOfflineOperation + &AddOfflineOperation + &DeleteOfflineOperation + &ProcessOfflineOperation + ); } =head1 NAME @@ -571,7 +581,7 @@ sub itemissues { =head2 CanBookBeIssued ( $issuingimpossible, $needsconfirmation ) = CanBookBeIssued( $borrower, - $barcode, $duedatespec, $inprocess ); + $barcode, $duedatespec, $inprocess, $ignore_reserves ); Check if a book can be issued. @@ -585,7 +595,8 @@ C<$issuingimpossible> and C<$needsconfirmation> are some hashref. =item C<$duedatespec> is a C4::Dates object. -=item C<$inprocess> +=item C<$inprocess> boolean switch +=item C<$ignore_reserves> boolean switch =back @@ -662,7 +673,7 @@ if the borrower borrows to much things =cut sub CanBookBeIssued { - my ( $borrower, $barcode, $duedate, $inprocess ) = @_; + 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 $item = GetItem(GetItemnumberFromBarcode( $barcode )); @@ -869,37 +880,40 @@ sub CanBookBeIssued { $needsconfirmation{issued_borrowernumber} = $currborinfo->{'borrowernumber'}; } - # See if the item is on reserve. - my ( $restype, $res, undef ) = C4::Reserves::CheckReserves( $item->{'itemnumber'} ); - if ($restype) { - my $resbor = $res->{'borrowernumber'}; - my ( $resborrower ) = C4::Members::GetMember( borrowernumber => $resbor ); - my $branches = GetBranches(); - my $branchname = $branches->{ $res->{'branchcode'} }->{'branchname'}; - if ( $resbor ne $borrower->{'borrowernumber'} && $restype eq "Waiting" ) - { - # The item is on reserve and waiting, but has been - # reserved by some other patron. - $needsconfirmation{RESERVE_WAITING} = 1; - $needsconfirmation{'resfirstname'} = $resborrower->{'firstname'}; - $needsconfirmation{'ressurname'} = $resborrower->{'surname'}; - $needsconfirmation{'rescardnumber'} = $resborrower->{'cardnumber'}; - $needsconfirmation{'resborrowernumber'} = $resborrower->{'borrowernumber'}; - $needsconfirmation{'resbranchname'} = $branchname; - $needsconfirmation{'reswaitingdate'} = format_date($res->{'waitingdate'}); - } - elsif ( $restype eq "Reserved" ) { - # The item is on reserve for someone else. - $needsconfirmation{RESERVED} = 1; - $needsconfirmation{'resfirstname'} = $resborrower->{'firstname'}; - $needsconfirmation{'ressurname'} = $resborrower->{'surname'}; - $needsconfirmation{'rescardnumber'} = $resborrower->{'cardnumber'}; - $needsconfirmation{'resborrowernumber'} = $resborrower->{'borrowernumber'}; - $needsconfirmation{'resbranchname'} = $branchname; - $needsconfirmation{'resreservedate'} = format_date($res->{'reservedate'}); + unless ( $ignore_reserves ) { + # See if the item is on reserve. + my ( $restype, $res ) = C4::Reserves::CheckReserves( $item->{'itemnumber'} ); + if ($restype) { + my $resbor = $res->{'borrowernumber'}; + if ( $resbor ne $borrower->{'borrowernumber'} ) { + my ( $resborrower ) = C4::Members::GetMember( borrowernumber => $resbor ); + my $branchname = GetBranchName( $res->{'branchcode'} ); + if ( $restype eq "Waiting" ) + { + # The item is on reserve and waiting, but has been + # reserved by some other patron. + $needsconfirmation{RESERVE_WAITING} = 1; + $needsconfirmation{'resfirstname'} = $resborrower->{'firstname'}; + $needsconfirmation{'ressurname'} = $resborrower->{'surname'}; + $needsconfirmation{'rescardnumber'} = $resborrower->{'cardnumber'}; + $needsconfirmation{'resborrowernumber'} = $resborrower->{'borrowernumber'}; + $needsconfirmation{'resbranchname'} = $branchname; + $needsconfirmation{'reswaitingdate'} = format_date($res->{'waitingdate'}); + } + elsif ( $restype eq "Reserved" ) { + # The item is on reserve for someone else. + $needsconfirmation{RESERVED} = 1; + $needsconfirmation{'resfirstname'} = $resborrower->{'firstname'}; + $needsconfirmation{'ressurname'} = $resborrower->{'surname'}; + $needsconfirmation{'rescardnumber'} = $resborrower->{'cardnumber'}; + $needsconfirmation{'resborrowernumber'} = $resborrower->{'borrowernumber'}; + $needsconfirmation{'resbranchname'} = $branchname; + $needsconfirmation{'resreservedate'} = format_date($res->{'reservedate'}); + } + } } } - return ( \%issuingimpossible, \%needsconfirmation ); + return ( \%issuingimpossible, \%needsconfirmation ); } =head2 AddIssue @@ -1025,6 +1039,12 @@ sub AddIssue { CartToShelf( $item->{'itemnumber'} ); } $item->{'issues'}++; + + ## If item was lost, it has now been found, reverse any list item charges if neccessary. + if ( $item->{'itemlost'} ) { + _FixAccountForLostAndReturned( $item->{'itemnumber'}, undef, $item->{'barcode'} ); + } + ModItem({ issues => $item->{'issues'}, holdingbranch => C4::Context->userenv->{'branch'}, itemlost => 0, @@ -1345,13 +1365,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 @@ -1359,7 +1383,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 @@ -1369,33 +1393,36 @@ 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 ); # 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 @@ -1512,9 +1539,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 @@ -1958,8 +1986,8 @@ sub _GetCircControlBranch { my $circcontrol = C4::Context->preference('CircControl'); my $branch; - if ($circcontrol eq 'PickupLibrary') { - $branch= C4::Context->userenv->{'branch'} if C4::Context->userenv; + if ($circcontrol eq 'PickupLibrary' and (C4::Context->userenv and C4::Context->userenv->{'branch'}) ) { + $branch= C4::Context->userenv->{'branch'}; } elsif ($circcontrol eq 'PatronLibrary') { $branch=$borrower->{branchcode}; } else { @@ -2657,11 +2685,18 @@ sub SendCirculationAlert { borrowernumber => $borrower->{borrowernumber}, message_name => $message_name{$type}, }); - my $letter = C4::Letters::getletter('circulation', $type); - C4::Letters::parseletter($letter, 'biblio', $item->{biblionumber}); - C4::Letters::parseletter($letter, 'biblioitems', $item->{biblionumber}); - C4::Letters::parseletter($letter, 'borrowers', $borrower->{borrowernumber}); - C4::Letters::parseletter($letter, 'branches', $branch); + my $letter = C4::Letters::GetPreparedLetter ( + module => 'circulation', + letter_code => $type, + branchcode => $branch, + tables => { + 'biblio' => $item->{biblionumber}, + 'biblioitems' => $item->{biblionumber}, + 'borrowers' => $borrower, + 'branches' => $branch, + } + ) or return; + my @transports = @{ $borrower_preferences->{transports} }; # warn "no transports" unless @transports; for (@transports) { @@ -2676,7 +2711,8 @@ sub SendCirculationAlert { $message->update; } } - $letter; + + return $letter; } =head2 updateWrongTransfer @@ -2968,14 +3004,17 @@ sub CreateBranchTransferLimit { =head2 DeleteBranchTransferLimits - DeleteBranchTransferLimits(); +DeleteBranchTransferLimits($frombranch); + +Deletes all the branch transfer limits for one branch =cut sub DeleteBranchTransferLimits { - my $dbh = C4::Context->dbh; - my $sth = $dbh->prepare("TRUNCATE TABLE branch_transfer_limits"); - $sth->execute(); + my $branch = shift; + my $dbh = C4::Context->dbh; + my $sth = $dbh->prepare("DELETE FROM branch_transfer_limits WHERE fromBranch = ?"); + $sth->execute($branch); } sub ReturnLostItem{ @@ -3014,6 +3053,145 @@ sub LostItem{ } } +sub GetOfflineOperations { + my $dbh = C4::Context->dbh; + my $sth = $dbh->prepare("SELECT * FROM pending_offline_operations WHERE branchcode=? ORDER BY timestamp"); + $sth->execute(C4::Context->userenv->{'branch'}); + my $results = $sth->fetchall_arrayref({}); + $sth->finish; + return $results; +} + +sub GetOfflineOperation { + my $dbh = C4::Context->dbh; + my $sth = $dbh->prepare("SELECT * FROM pending_offline_operations WHERE operationid=?"); + $sth->execute( shift ); + my $result = $sth->fetchrow_hashref; + $sth->finish; + return $result; +} + +sub AddOfflineOperation { + my $dbh = C4::Context->dbh; + my $sth = $dbh->prepare("INSERT INTO pending_offline_operations (userid, branchcode, timestamp, action, barcode, cardnumber) VALUES(?,?,?,?,?,?)"); + $sth->execute( @_ ); + return "Added."; +} + +sub DeleteOfflineOperation { + my $dbh = C4::Context->dbh; + my $sth = $dbh->prepare("DELETE FROM pending_offline_operations WHERE operationid=?"); + $sth->execute( shift ); + return "Deleted."; +} + +sub ProcessOfflineOperation { + my $operation = shift; + + my $report; + if ( $operation->{action} eq 'return' ) { + $report = ProcessOfflineReturn( $operation ); + } elsif ( $operation->{action} eq 'issue' ) { + $report = ProcessOfflineIssue( $operation ); + } + + DeleteOfflineOperation( $operation->{operationid} ) if $operation->{operationid}; + + return $report; +} + +sub ProcessOfflineReturn { + my $operation = shift; + + my $itemnumber = C4::Items::GetItemnumberFromBarcode( $operation->{barcode} ); + + if ( $itemnumber ) { + my $issue = GetOpenIssue( $itemnumber ); + if ( $issue ) { + MarkIssueReturned( + $issue->{borrowernumber}, + $itemnumber, + undef, + $operation->{timestamp}, + ); + ModItem( + { renewals => 0, onloan => undef }, + $issue->{'biblionumber'}, + $itemnumber + ); + return "Success."; + } else { + return "Item not issued."; + } + } else { + return "Item not found."; + } +} + +sub ProcessOfflineIssue { + my $operation = shift; + + my $borrower = C4::Members::GetMemberDetails( undef, $operation->{cardnumber} ); # Get borrower from operation cardnumber + + if ( $borrower->{borrowernumber} ) { + my $itemnumber = C4::Items::GetItemnumberFromBarcode( $operation->{barcode} ); + unless ($itemnumber) { + return "Barcode not found."; + } + my $issue = GetOpenIssue( $itemnumber ); + + if ( $issue and ( $issue->{borrowernumber} ne $borrower->{borrowernumber} ) ) { # Item already issued to another borrower, mark it returned + MarkIssueReturned( + $issue->{borrowernumber}, + $itemnumber, + undef, + $operation->{timestamp}, + ); + } + AddIssue( + $borrower, + $operation->{'barcode'}, + undef, + 1, + $operation->{timestamp}, + undef, + ); + return "Success."; + } else { + return "Borrower not found."; + } +} + + + +=head2 TransferSlip + + TransferSlip($user_branch, $itemnumber, $to_branch) + + Returns letter hash ( see C4::Letters::GetPreparedLetter ) or undef + +=cut + +sub TransferSlip { + my ($branch, $itemnumber, $to_branch) = @_; + + my $item = GetItem( $itemnumber ) + or return; + + my $pulldate = C4::Dates->new(); + + return C4::Letters::GetPreparedLetter ( + module => 'circulation', + letter_code => 'TRANSFERSLIP', + branchcode => $branch, + tables => { + 'branches' => $to_branch, + 'biblio' => $item->{biblionumber}, + 'items' => $item, + }, + ); +} + 1;