package C4::Reserves2; #assumes C4/Reserves2 # Copyright 2000-2002 Katipo Communications # # This file is part of Koha. # # Koha is free software; you can redistribute it and/or modify it under the # terms of the GNU General Public License as published by the Free Software # Foundation; either version 2 of the License, or (at your option) any later # version. # # Koha is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR # A PARTICULAR PURPOSE. See the GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along with # Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place, # Suite 330, Boston, MA 02111-1307 USA use strict; require Exporter; use DBI; use C4::Context; use C4::Search; # FIXME - C4::Reserves2 uses C4::Search, which uses C4::Reserves2. # So Perl complains that all of the functions here get redefined. #use C4::Accounts; use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS); # set the version for version checking $VERSION = 0.01; @ISA = qw(Exporter); @EXPORT = qw(&FindReserves &CheckReserves &CheckWaiting &CancelReserve &FillReserve &ReserveWaiting &CreateReserve &updatereserves &UpdateReserve &getreservetitle &Findgroupreserve); # make all your functions, whether exported or not; sub FindReserves { my ($bib,$bor)=@_; my $dbh = C4::Context->dbh; my $query="SELECT *,reserves.branchcode,biblio.title AS btitle FROM reserves,borrowers,biblio "; if ($bib ne ''){ $bib = $dbh->quote($bib); if ($bor ne ''){ $bor = $dbh->quote($bor); $query .= " where reserves.biblionumber = $bib and borrowers.borrowernumber = $bor and reserves.borrowernumber = borrowers.borrowernumber and biblio.biblionumber = $bib and cancellationdate is NULL and (found <> 'F' or found is NULL)"; } else { $query .= " where reserves.borrowernumber = borrowers.borrowernumber and biblio.biblionumber = $bib and reserves.biblionumber = $bib and cancellationdate is NULL and (found <> 'F' or found is NULL)"; } } else { $query .= " where borrowers.borrowernumber = $bor and reserves.borrowernumber = borrowers.borrowernumber and reserves.biblionumber = biblio.biblionumber and cancellationdate is NULL and (found <> 'F' or found is NULL)"; } $query.=" order by priority"; my $sth=$dbh->prepare($query); $sth->execute; my $i=0; my @results; while (my $data=$sth->fetchrow_hashref){ if ($data->{'constrainttype'} eq 'o') { my $conquery = "SELECT biblioitemnumber FROM reserveconstraints WHERE biblionumber = ? AND borrowernumber = ? AND reservedate = ?"; my $csth=$dbh->prepare($conquery); my $bibn = $data->{'biblionumber'}; my $born = $data->{'borrowernumber'}; my $resd = $data->{'reservedate'}; $csth->execute($bibn, $born, $resd); my ($bibitemno) = $csth->fetchrow_array; $csth->finish; my $bdata = C4::Search::bibitemdata($bibitemno); foreach my $key (keys %$bdata) { $data->{$key} = $bdata->{$key}; } } $results[$i]=$data; $i++; } # print $query; $sth->finish; return($i,\@results); } sub CheckReserves { my ($item, $barcode) = @_; # warn "In CheckReserves: itemnumber = $item"; my $dbh = C4::Context->dbh; my $sth; if ($item) { my $qitem=$dbh->quote($item); # get the biblionumber... $sth=$dbh->prepare("SELECT items.biblionumber, items.biblioitemnumber, itemtypes.notforloan FROM items, biblioitems, itemtypes WHERE items.biblioitemnumber = biblioitems.biblioitemnumber AND biblioitems.itemtype = itemtypes.itemtype AND itemnumber=$qitem"); } else { my $qbc=$dbh->quote($barcode); # get the biblionumber... $sth=$dbh->prepare("SELECT items.biblionumber, items.biblioitemnumber, itemtypes.notforloan FROM items, biblioitems, itemtypes WHERE items.biblioitemnumber = biblioitems.biblioitemnumber AND biblioitems.itemtype = itemtypes.itemtype AND barcode=$qbc"); # FIXME - This function uses $item later on. Ought to set it here. } $sth->execute; my ($biblio, $bibitem, $notforloan) = $sth->fetchrow_array; $sth->finish; # if item is not for loan it cannot be reserved either..... return (0, 0) if ($notforloan); # get the reserves... my ($count, @reserves) = Findgroupreserve($bibitem, $biblio); my $priority = 10000000; my $highest; if ($count) { foreach my $res (@reserves) { # FIXME - $item might be undefined or empty: the caller # might be searching by barcode. if ($res->{'itemnumber'} == $item) { return ("Waiting", $res); } else { if ($res->{'priority'} != 0 && $res->{'priority'} < $priority) { $priority = $res->{'priority'}; $highest = $res; } } } } if ($highest) { # FIXME - $highest might be undefined $highest->{'itemnumber'} = $item; return ("Reserved", $highest); } else { return (0, 0); } } sub CancelReserve { my ($biblio, $item, $borr) = @_; my $dbh = C4::Context->dbh; #warn "In CancelReserve"; if (($item and $borr) and (not $biblio)) { # removing a waiting reserve record.... $item = $dbh->quote($item); $borr = $dbh->quote($borr); # update the database... my $query = "update reserves set cancellationdate = now(), found = Null, priority = 0 where itemnumber = $item and borrowernumber = $borr"; my $sth = $dbh->prepare($query); $sth->execute; $sth->finish; } if (($biblio and $borr) and (not $item)) { # removing a reserve record.... my $q_biblio = $dbh->quote($biblio); $borr = $dbh->quote($borr); # get the prioritiy on this record.... my $query = "SELECT priority FROM reserves WHERE biblionumber = $q_biblio AND borrowernumber = $borr AND cancellationdate is NULL AND (found <> 'F' or found is NULL)"; my $sth=$dbh->prepare($query); $sth->execute; my ($priority) = $sth->fetchrow_array; $sth->finish; # update the database, removing the record... # FIXME - There's already a $query in this scope. my $query = "update reserves set cancellationdate = now(), found = Null, priority = 0 where biblionumber = $q_biblio and borrowernumber = $borr and cancellationdate is NULL and (found <> 'F' or found is NULL)"; # FIXME - There's already a $query in this scope. # FIXME - There's already a $sth in this scope. my $sth = $dbh->prepare($query); # FIXME - There's already a $sth in this scope. $sth->execute; $sth->finish; # now fix the priority on the others.... fixpriority($priority, $biblio); } } sub FillReserve { my ($res) = @_; my $dbh = C4::Context->dbh; # fillinf a reserve record.... my $biblio = $res->{'biblionumber'}; my $qbiblio = $dbh->quote($biblio); my $borr = $res->{'borrowernumber'}; $borr = $dbh->quote($borr); my $resdate = $res->{'reservedate'}; $resdate = $dbh->quote($resdate); # get the prioritiy on this record.... my $query = "SELECT priority FROM reserves WHERE biblionumber = $qbiblio AND borrowernumber = $borr AND reservedate = $resdate)"; my $sth=$dbh->prepare($query); $sth->execute; my ($priority) = $sth->fetchrow_array; $sth->finish; # update the database... # FIXME - There's already a $query in this scope. my $query = "UPDATE reserves SET found = 'F', priority = 0 WHERE biblionumber = $qbiblio AND reservedate = $resdate AND borrowernumber = $borr"; # FIXME - There's already a $query in this scope. # FIXME - There's already a $sth in this scope. my $sth = $dbh->prepare($query); # FIXME - There's already a $sth in this scope. $sth->execute; $sth->finish; # now fix the priority on the others (if the priority wasnt already sorted!).... unless ($priority == 0) { fixpriority($priority, $biblio); } } sub fixpriority { my ($priority, $biblio) = @_; my $dbh = C4::Context->dbh; my ($count, $reserves) = FindReserves($biblio); foreach my $rec (@$reserves) { if ($rec->{'priority'} > $priority) { my $newpr = $rec->{'priority'}; $newpr = $dbh->quote($newpr - 1); my $nbib = $rec->{'biblionumber'}; $nbib = $dbh->quote($nbib); my $nbor = $rec->{'borrowernumber'}; $nbor = $dbh->quote($nbor); my $nresd = $rec->{'reservedate'}; $nresd = $dbh->quote($nresd); my $query = "UPDATE reserves SET priority = $newpr WHERE biblionumber = $nbib AND borrowernumber = $nbor AND reservedate = $nresd"; #warn $query; my $sth = $dbh->prepare($query); $sth->execute; $sth->finish; } } } sub ReserveWaiting { my ($item, $borr) = @_; my $dbh = C4::Context->dbh; $item = $dbh->quote($item); $borr = $dbh->quote($borr); # get priority and biblionumber.... my $query = "SELECT reserves.priority as priority, reserves.biblionumber as biblionumber, reserves.branchcode as branchcode, reserves.timestamp as timestamp FROM reserves,items WHERE reserves.biblionumber = items.biblionumber AND items.itemnumber = $item AND reserves.borrowernumber = $borr AND reserves.cancellationdate is NULL AND (reserves.found <> 'F' or reserves.found is NULL)"; my $sth = $dbh->prepare($query); $sth->execute; my $data = $sth->fetchrow_hashref; $sth->finish; my $biblio = $data->{'biblionumber'}; my $timestamp = $data->{'timestamp'}; my $q_biblio = $dbh->quote($biblio); my $q_timestamp = $dbh->quote($timestamp); warn "Timestamp: ".$timestamp."\n"; # update reserves record.... $query = "UPDATE reserves SET priority = 0, found = 'W', itemnumber = $item WHERE borrowernumber = $borr AND biblionumber = $q_biblio AND timestamp = $q_timestamp"; warn "Query: ".$query."\n"; $sth = $dbh->prepare($query); $sth->execute; $sth->finish; # now fix up the remaining priorities.... fixpriority($data->{'priority'}, $biblio); my $branchcode = $data->{'branchcode'}; return $branchcode; } sub CheckWaiting { my ($borr)=@_; my $dbh = C4::Context->dbh; $borr = $dbh->quote($borr); my @itemswaiting; my $query = "SELECT * FROM reserves WHERE borrowernumber = $borr AND reserves.found = 'W' AND cancellationdate is NULL"; my $sth = $dbh->prepare($query); $sth->execute(); # FIXME - Use 'push' my $cnt=0; if (my $data=$sth->fetchrow_hashref) { $itemswaiting[$cnt] =$data; $cnt ++; } $sth->finish; return ($cnt,\@itemswaiting); } sub Findgroupreserve { my ($bibitem,$biblio)=@_; my $dbh = C4::Context->dbh; $bibitem=$dbh->quote($bibitem); my $query = "SELECT reserves.biblionumber AS biblionumber, reserves.borrowernumber AS borrowernumber, reserves.reservedate AS reservedate, reserves.branchcode AS branchcode, reserves.cancellationdate AS cancellationdate, reserves.found AS found, reserves.reservenotes AS reservenotes, reserves.priority AS priority, reserves.timestamp AS timestamp, reserveconstraints.biblioitemnumber AS biblioitemnumber, reserves.itemnumber AS itemnumber FROM reserves LEFT JOIN reserveconstraints ON reserves.biblionumber = reserveconstraints.biblionumber WHERE reserves.biblionumber = $biblio AND ( ( reserveconstraints.biblioitemnumber = $bibitem AND reserves.borrowernumber = reserveconstraints.borrowernumber AND reserves.reservedate =reserveconstraints.reservedate ) OR reserves.constrainttype='a' ) AND reserves.cancellationdate is NULL AND (reserves.found <> 'F' or reserves.found is NULL)"; my $sth=$dbh->prepare($query); $sth->execute; my $i=0; my @results; while (my $data=$sth->fetchrow_hashref){ $results[$i]=$data; $i++; } $sth->finish; return($i,@results); } sub CreateReserve { my ($env,$branch,$borrnum,$biblionumber,$constraint,$bibitems,$priority,$notes,$title)= @_; my $fee=CalcReserveFee($env,$borrnum,$biblionumber,$constraint,$bibitems); my $dbh = C4::Context->dbh; my $const = lc substr($constraint,0,1); my @datearr = localtime(time); my $resdate =(1900+$datearr[5])."-".($datearr[4]+1)."-".$datearr[3]; #eval { # updates take place here if ($fee > 0) { # print $fee; my $nextacctno = &getnextacctno($env,$borrnum,$dbh); my $updquery = "insert into accountlines (borrowernumber,accountno,date,amount,description,accounttype,amountoutstanding) values ($borrnum,$nextacctno,now(),$fee,'Reserve Charge - $title','Res',$fee)"; my $usth = $dbh->prepare($updquery); $usth->execute; $usth->finish; } #if ($const eq 'a'){ my $query="insert into reserves (borrowernumber,biblionumber,reservedate,branchcode,constrainttype,priority,reservenotes) values ('$borrnum','$biblionumber','$resdate','$branch','$const','$priority','$notes')"; my $sth = $dbh->prepare($query); $sth->execute(); $sth->finish; #} if (($const eq "o") || ($const eq "e")) { my $numitems = @$bibitems; my $i = 0; while ($i < $numitems) { my $biblioitem = @$bibitems[$i]; my $query = "insert into reserveconstraints (borrowernumber,biblionumber,reservedate,biblioitemnumber) values ('$borrnum','$biblionumber','$resdate','$biblioitem')"; my $sth = $dbh->prepare($query); $sth->execute(); $sth->finish; $i++; } } # print $query; return(); } sub CalcReserveFee { my ($env,$borrnum,$biblionumber,$constraint,$bibitems) = @_; #check for issues; my $dbh = C4::Context->dbh; my $const = lc substr($constraint,0,1); my $query = "SELECT * FROM borrowers,categories WHERE (borrowernumber = ?) AND (borrowers.categorycode = categories.categorycode)"; my $sth = $dbh->prepare($query); $sth->execute($borrnum); my $data = $sth->fetchrow_hashref; $sth->finish(); my $fee = $data->{'reservefee'}; my $cntitems = @->$bibitems; if ($fee > 0) { # check for items on issue # first find biblioitem records my @biblioitems; my $query1 = "SELECT * FROM biblio,biblioitems WHERE (biblio.biblionumber = ?) AND (biblio.biblionumber = biblioitems.biblionumber)"; my $sth1 = $dbh->prepare($query1); $sth1->execute($biblionumber); while (my $data1=$sth1->fetchrow_hashref) { if ($const eq "a") { push @biblioitems,$data1; } else { my $found = 0; my $x = 0; while ($x < $cntitems) { if (@$bibitems->{'biblioitemnumber'} == $data->{'biblioitemnumber'}) { $found = 1; } $x++; } if ($const eq 'o') { if ( $found == 1) { push @biblioitems,$data1; } } else { if ($found == 0) { push @biblioitems,$data1; } } } } $sth1->finish; my $cntitemsfound = @biblioitems; my $issues = 0; my $x = 0; my $allissued = 1; while ($x < $cntitemsfound) { my $bitdata = $biblioitems[$x]; my $query2 = "SELECT * FROM items WHERE biblioitemnumber = ?"; my $sth2 = $dbh->prepare($query2); $sth2->execute($bitdata->{'biblioitemnumber'}); while (my $itdata=$sth2->fetchrow_hashref) { my $query3 = "SELECT * FROM issues WHERE itemnumber = ? AND returndate IS NULL"; my $sth3 = $dbh->prepare($query3); $sth3->execute($itdata->{'itemnumber'}); if (my $isdata=$sth3->fetchrow_hashref) { } else { $allissued = 0; } } $x++; } if ($allissued == 0) { my $rquery = "SELECT * FROM reserves WHERE biblionumber = ?"; my $rsth = $dbh->prepare($rquery); $rsth->execute($biblionumber); if (my $rdata = $rsth->fetchrow_hashref) { } else { $fee = 0; } } } # print "fee $fee"; return $fee; } sub getnextacctno { my ($env,$bornumber,$dbh)=@_; my $nextaccntno = 1; my $query = "select * from accountlines where (borrowernumber = '$bornumber') order by accountno desc"; my $sth = $dbh->prepare($query); $sth->execute; if (my $accdata=$sth->fetchrow_hashref){ $nextaccntno = $accdata->{'accountno'} + 1; } $sth->finish; return($nextaccntno); } sub updatereserves{ #subroutine to update a reserve my ($rank,$biblio,$borrower,$del,$branch)=@_; my $dbh = C4::Context->dbh; my $query="Update reserves "; if ($del == 0){ $query.="set priority='$rank',branchcode='$branch' where biblionumber=$biblio and borrowernumber=$borrower"; } else { $query="Select * from reserves where biblionumber=$biblio and borrowernumber=$borrower"; my $sth=$dbh->prepare($query); $sth->execute; my $data=$sth->fetchrow_hashref; $sth->finish; $query="Select * from reserves where biblionumber=$biblio and priority > '$data->{'priority'}' and cancellationdate is NULL order by priority"; my $sth2=$dbh->prepare($query) || die $dbh->errstr; $sth2->execute || die $sth2->errstr; while (my $data=$sth2->fetchrow_hashref){ $data->{'priority'}--; $query="Update reserves set priority=$data->{'priority'} where biblionumber=$data->{'biblionumber'} and borrowernumber=$data->{'borrowernumber'}"; my $sth3=$dbh->prepare($query); $sth3->execute || die $sth3->errstr; $sth3->finish; } $sth2->finish; $query="update reserves set cancellationdate=now() where biblionumber=$biblio and borrowernumber=$borrower"; } my $sth=$dbh->prepare($query); $sth->execute; $sth->finish; } sub UpdateReserve { #subroutine to update a reserve my ($rank,$biblio,$borrower,$branch)=@_; return if $rank eq "W"; my $dbh = C4::Context->dbh; if ($rank eq "del") { my $query = "UPDATE reserves SET cancellationdate=now() WHERE biblionumber = ? AND borrowernumber = ? AND cancellationdate is NULL AND (found <> 'F' or found is NULL)"; my $sth=$dbh->prepare($query); $sth->execute($biblio, $borrower); $sth->finish; } else { my $query = "UPDATE reserves SET priority = ? ,branchcode = ?, itemnumber = NULL, found = NULL WHERE biblionumber = ? AND borrowernumber = ? AND cancellationdate is NULL AND (found <> 'F' or found is NULL)"; my $sth=$dbh->prepare($query); $sth->execute($rank, $branch, $biblio, $borrower); $sth->finish; } } sub getreservetitle { my ($biblio,$bor,$date,$timestamp)=@_; my $dbh = C4::Context->dbh; my $query="Select * from reserveconstraints,biblioitems where reserveconstraints.biblioitemnumber=biblioitems.biblioitemnumber and reserveconstraints.biblionumber=$biblio and reserveconstraints.borrowernumber = $bor and reserveconstraints.reservedate='$date' and reserveconstraints.timestamp=$timestamp"; my $sth=$dbh->prepare($query); $sth->execute; my $data=$sth->fetchrow_hashref; $sth->finish; # print $query; return($data); } END { } # module clean-up code here (global destructor)