From 8e41022b0d488dad005bf5d0f4388f1a74fb0df6 Mon Sep 17 00:00:00 2001 From: Galen Charlton Date: Thu, 3 Jan 2008 12:36:33 -0600 Subject: [PATCH] item rework: moved various accessor functions Moved following functions from C4::Biblio to C4::Items: GetItemStatus GetItemLocation GetLostItems GetItemsForInventory GetItemsCount GetItemInfosOf GetItemsByBiblioitemnumber GetItemsInfo get_itemnumbers_of Signed-off-by: Chris Cormack Signed-off-by: Joshua Ferraro --- C4/Biblio.pm | 613 --------------------------------- C4/Items.pm | 672 ++++++++++++++++++++++++++++++++++++- C4/XISBN.pm | 1 + catalogue/ISBDdetail.pl | 1 + catalogue/MARCdetail.pl | 1 + catalogue/detail.pl | 1 + catalogue/detailprint.pl | 1 + catalogue/moredetail.pl | 1 + opac/opac-basket.pl | 1 + opac/opac-detail.pl | 1 + opac/opac-sendbasket.pl | 1 + reports/itemslost.pl | 3 +- reports/reservereport.pl | 3 +- reserve/request.pl | 1 + serials/routing-preview.pl | 1 + serials/serials-recieve.pl | 1 + 16 files changed, 686 insertions(+), 617 deletions(-) diff --git a/C4/Biblio.pm b/C4/Biblio.pm index d637cf792a..37fda9393e 100755 --- a/C4/Biblio.pm +++ b/C4/Biblio.pm @@ -52,13 +52,6 @@ push @EXPORT, qw( &GetBiblioItemByBiblioNumber &GetBiblioFromItemNumber - &GetItemInfosOf - &GetItemStatus - &GetItemLocation - &GetLostItems - &GetItemsForInventory - &GetItemsCount - &GetMarcNotes &GetMarcSubjects &GetMarcBiblio @@ -67,10 +60,7 @@ push @EXPORT, qw( GetMarcUrls &GetUsedMarcStructure - &GetItemsInfo - &GetItemsByBiblioitemnumber &GetItemnumberFromBarcode - &get_itemnumbers_of &GetXmlBiblio &GetAuthorisedValueDesc @@ -702,468 +692,6 @@ sub GetBiblioData { return ($data); } # sub GetBiblioData - -=head2 GetItemsInfo - -=over 4 - - @results = &GetItemsInfo($biblionumber, $type); - -Returns information about books with the given biblionumber. - -C<$type> may be either C or anything else. If it is not set to -C, then the search will exclude lost, very overdue, and -withdrawn items. - -C<&GetItemsInfo> returns a list of references-to-hash. Each element -contains a number of keys. Most of them are table items from the -C, C, C, and C tables in the -Koha database. Other keys include: - -=over 4 - -=item C<$data-E{branchname}> - -The name (not the code) of the branch to which the book belongs. - -=item C<$data-E{datelastseen}> - -This is simply C, except that while the date is -stored in YYYY-MM-DD format in the database, here it is converted to -DD/MM/YYYY format. A NULL date is returned as C. - -=item C<$data-E{datedue}> - -=item C<$data-E{class}> - -This is the concatenation of C, the book's -Dewey code, and C. - -=item C<$data-E{ocount}> - -I think this is the number of copies of the book available. - -=item C<$data-E{order}> - -If this is set, it is set to C. - -=back - -=back - -=cut - -sub GetItemsInfo { - my ( $biblionumber, $type ) = @_; - my $dbh = C4::Context->dbh; - my $query = "SELECT *,items.notforloan as itemnotforloan - FROM items - LEFT JOIN biblio ON biblio.biblionumber = items.biblionumber - LEFT JOIN biblioitems ON biblioitems.biblioitemnumber = items.biblioitemnumber"; - $query .= (C4::Context->preference('item-level_itypes')) ? - " LEFT JOIN itemtypes on items.itype = itemtypes.itemtype " - : " LEFT JOIN itemtypes on biblioitems.itemtype = itemtypes.itemtype "; - $query .= "WHERE items.biblionumber = ? ORDER BY items.dateaccessioned desc" ; - my $sth = $dbh->prepare($query); - $sth->execute($biblionumber); - my $i = 0; - my @results; - my ( $date_due, $count_reserves ); - - my $isth = $dbh->prepare( - "SELECT issues.*,borrowers.cardnumber,borrowers.surname,borrowers.firstname,borrowers.branchcode as bcode - FROM issues LEFT JOIN borrowers ON issues.borrowernumber=borrowers.borrowernumber - WHERE itemnumber = ? - AND returndate IS NULL" - ); - while ( my $data = $sth->fetchrow_hashref ) { - my $datedue = ''; - $isth->execute( $data->{'itemnumber'} ); - if ( my $idata = $isth->fetchrow_hashref ) { - $data->{borrowernumber} = $idata->{borrowernumber}; - $data->{cardnumber} = $idata->{cardnumber}; - $data->{surname} = $idata->{surname}; - $data->{firstname} = $idata->{firstname}; - $datedue = $idata->{'date_due'}; - if (C4::Context->preference("IndependantBranches")){ - my $userenv = C4::Context->userenv; - if ( ($userenv) && ( $userenv->{flags} != 1 ) ) { - $data->{'NOTSAMEBRANCH'} = 1 if ($idata->{'bcode'} ne $userenv->{branch}); - } - } - } - if ( $datedue eq '' ) { - my ( $restype, $reserves ) = - C4::Reserves::CheckReserves( $data->{'itemnumber'} ); - if ($restype) { - $count_reserves = $restype; - } - } - $isth->finish; - - #get branch information..... - my $bsth = $dbh->prepare( - "SELECT * FROM branches WHERE branchcode = ? - " - ); - $bsth->execute( $data->{'holdingbranch'} ); - if ( my $bdata = $bsth->fetchrow_hashref ) { - $data->{'branchname'} = $bdata->{'branchname'}; - } - $data->{'datedue'} = $datedue; - $data->{'count_reserves'} = $count_reserves; - - # get notforloan complete status if applicable - my $sthnflstatus = $dbh->prepare( - 'SELECT authorised_value - FROM marc_subfield_structure - WHERE kohafield="items.notforloan" - ' - ); - - $sthnflstatus->execute; - my ($authorised_valuecode) = $sthnflstatus->fetchrow; - if ($authorised_valuecode) { - $sthnflstatus = $dbh->prepare( - "SELECT lib FROM authorised_values - WHERE category=? - AND authorised_value=?" - ); - $sthnflstatus->execute( $authorised_valuecode, - $data->{itemnotforloan} ); - my ($lib) = $sthnflstatus->fetchrow; - $data->{notforloan} = $lib; - } - - # my stack procedures - my $stackstatus = $dbh->prepare( - 'SELECT authorised_value - FROM marc_subfield_structure - WHERE kohafield="items.stack" - ' - ); - $stackstatus->execute; - - ($authorised_valuecode) = $stackstatus->fetchrow; - if ($authorised_valuecode) { - $stackstatus = $dbh->prepare( - "SELECT lib - FROM authorised_values - WHERE category=? - AND authorised_value=? - " - ); - $stackstatus->execute( $authorised_valuecode, $data->{stack} ); - my ($lib) = $stackstatus->fetchrow; - $data->{stack} = $lib; - } - # Find the last 3 people who borrowed this item. - my $sth2 = $dbh->prepare("SELECT * FROM issues,borrowers - WHERE itemnumber = ? - AND issues.borrowernumber = borrowers.borrowernumber - AND returndate IS NOT NULL LIMIT 3"); - $sth2->execute($data->{'itemnumber'}); - my $ii = 0; - while (my $data2 = $sth2->fetchrow_hashref()) { - $data->{"timestamp$ii"} = $data2->{'timestamp'} if $data2->{'timestamp'}; - $data->{"card$ii"} = $data2->{'cardnumber'} if $data2->{'cardnumber'}; - $data->{"borrower$ii"} = $data2->{'borrowernumber'} if $data2->{'borrowernumber'}; - $ii++; - } - - $results[$i] = $data; - $i++; - } - $sth->finish; - - return (@results); -} - -=head2 getitemstatus - -=over 4 - -$itemstatushash = &getitemstatus($fwkcode); -returns information about status. -Can be MARC dependant. -fwkcode is optional. -But basically could be can be loan or not -Create a status selector with the following code - -=head3 in PERL SCRIPT - -my $itemstatushash = getitemstatus; -my @itemstatusloop; -foreach my $thisstatus (keys %$itemstatushash) { - my %row =(value => $thisstatus, - statusname => $itemstatushash->{$thisstatus}->{'statusname'}, - ); - push @itemstatusloop, \%row; -} -$template->param(statusloop=>\@itemstatusloop); - - -=head3 in TEMPLATE - - - -=cut - -sub GetItemStatus { - - # returns a reference to a hash of references to status... - my ($fwk) = @_; - my %itemstatus; - my $dbh = C4::Context->dbh; - my $sth; - $fwk = '' unless ($fwk); - my ( $tag, $subfield ) = - GetMarcFromKohaField( "items.notforloan", $fwk ); - if ( $tag and $subfield ) { - my $sth = - $dbh->prepare( - "SELECT authorised_value - FROM marc_subfield_structure - WHERE tagfield=? - AND tagsubfield=? - AND frameworkcode=? - " - ); - $sth->execute( $tag, $subfield, $fwk ); - if ( my ($authorisedvaluecat) = $sth->fetchrow ) { - my $authvalsth = - $dbh->prepare( - "SELECT authorised_value,lib - FROM authorised_values - WHERE category=? - ORDER BY lib - " - ); - $authvalsth->execute($authorisedvaluecat); - while ( my ( $authorisedvalue, $lib ) = $authvalsth->fetchrow ) { - $itemstatus{$authorisedvalue} = $lib; - } - $authvalsth->finish; - return \%itemstatus; - exit 1; - } - else { - - #No authvalue list - # build default - } - $sth->finish; - } - - #No authvalue list - #build default - $itemstatus{"1"} = "Not For Loan"; - return \%itemstatus; -} - -=head2 getitemlocation - -=over 4 - -$itemlochash = &getitemlocation($fwk); -returns informations about location. -where fwk stands for an optional framework code. -Create a location selector with the following code - -=head3 in PERL SCRIPT - -my $itemlochash = getitemlocation; -my @itemlocloop; -foreach my $thisloc (keys %$itemlochash) { - my $selected = 1 if $thisbranch eq $branch; - my %row =(locval => $thisloc, - selected => $selected, - locname => $itemlochash->{$thisloc}, - ); - push @itemlocloop, \%row; -} -$template->param(itemlocationloop => \@itemlocloop); - -=head3 in TEMPLATE - - - -=back - -=cut - -sub GetItemLocation { - - # returns a reference to a hash of references to location... - my ($fwk) = @_; - my %itemlocation; - my $dbh = C4::Context->dbh; - my $sth; - $fwk = '' unless ($fwk); - my ( $tag, $subfield ) = - GetMarcFromKohaField( "items.location", $fwk ); - if ( $tag and $subfield ) { - my $sth = - $dbh->prepare( - "SELECT authorised_value - FROM marc_subfield_structure - WHERE tagfield=? - AND tagsubfield=? - AND frameworkcode=?" - ); - $sth->execute( $tag, $subfield, $fwk ); - if ( my ($authorisedvaluecat) = $sth->fetchrow ) { - my $authvalsth = - $dbh->prepare( - "SELECT authorised_value,lib - FROM authorised_values - WHERE category=? - ORDER BY lib" - ); - $authvalsth->execute($authorisedvaluecat); - while ( my ( $authorisedvalue, $lib ) = $authvalsth->fetchrow ) { - $itemlocation{$authorisedvalue} = $lib; - } - $authvalsth->finish; - return \%itemlocation; - exit 1; - } - else { - - #No authvalue list - # build default - } - $sth->finish; - } - - #No authvalue list - #build default - $itemlocation{"1"} = "Not For Loan"; - return \%itemlocation; -} - -=head2 GetLostItems - -$items = GetLostItems($where,$orderby); - -This function get the items lost into C<$items>. - -=over 2 - -=item input: -C<$where> is a hashref. it containts a field of the items table as key -and the value to match as value. -C<$orderby> is a field of the items table. - -=item return: -C<$items> is a reference to an array full of hasref which keys are items' table column. - -=item usage in the perl script: - -my %where; -$where{barcode} = 0001548; -my $items = GetLostItems( \%where, "homebranch" ); -$template->param(itemsloop => $items); - -=back - -=cut - -sub GetLostItems { - # Getting input args. - my $where = shift; - my $orderby = shift; - my $dbh = C4::Context->dbh; - - my $query = " - SELECT * - FROM items - WHERE itemlost IS NOT NULL - AND itemlost <> 0 - "; - foreach my $key (keys %$where) { - $query .= " AND " . $key . " LIKE '%" . $where->{$key} . "%'"; - } - $query .= " ORDER BY ".$orderby if defined $orderby; - - my $sth = $dbh->prepare($query); - $sth->execute; - my @items; - while ( my $row = $sth->fetchrow_hashref ){ - push @items, $row; - } - return \@items; -} - -=head2 GetItemsForInventory - -$itemlist = GetItemsForInventory($minlocation,$maxlocation,$datelastseen,$offset,$size) - -Retrieve a list of title/authors/barcode/callnumber, for biblio inventory. - -The sub returns a list of hashes, containing itemnumber, author, title, barcode & item callnumber. -It is ordered by callnumber,title. - -The minlocation & maxlocation parameters are used to specify a range of item callnumbers -the datelastseen can be used to specify that you want to see items not seen since a past date only. -offset & size can be used to retrieve only a part of the whole listing (defaut behaviour) - -=cut - -sub GetItemsForInventory { - my ( $minlocation, $maxlocation,$location, $datelastseen, $branch, $offset, $size ) = @_; - my $dbh = C4::Context->dbh; - my $sth; - if ($datelastseen) { - $datelastseen=format_date_in_iso($datelastseen); - my $query = - "SELECT itemnumber,barcode,itemcallnumber,title,author,biblio.biblionumber,datelastseen - FROM items - LEFT JOIN biblio ON items.biblionumber=biblio.biblionumber - WHERE itemcallnumber>= ? - AND itemcallnumber <=? - AND (datelastseen< ? OR datelastseen IS NULL)"; - $query.= " AND items.location=".$dbh->quote($location) if $location; - $query.= " AND items.homebranch=".$dbh->quote($branch) if $branch; - $query .= " ORDER BY itemcallnumber,title"; - $sth = $dbh->prepare($query); - $sth->execute( $minlocation, $maxlocation, $datelastseen ); - } - else { - my $query =" - SELECT itemnumber,barcode,itemcallnumber,biblio.biblionumber,title,author,datelastseen - FROM items - LEFT JOIN biblio ON items.biblionumber=biblio.biblionumber - WHERE itemcallnumber>= ? - AND itemcallnumber <=?"; - $query.= " AND items.location=".$dbh->quote($location) if $location; - $query.= " AND items.homebranch=".$dbh->quote($branch) if $branch; - $query .= " ORDER BY itemcallnumber,title"; - $sth = $dbh->prepare($query); - $sth->execute( $minlocation, $maxlocation ); - } - my @results; - while ( my $row = $sth->fetchrow_hashref ) { - $offset-- if ($offset); - $row->{datelastseen}=format_date($row->{datelastseen}); - if ( ( !$offset ) && $size ) { - push @results, $row; - $size--; - } - } - return \@results; -} - =head2 &GetBiblioItemData =over 4 @@ -1310,128 +838,6 @@ sub GetBiblio { return ( $count, @results ); } # sub GetBiblio -=head2 get_itemnumbers_of - -=over 4 - -my @itemnumbers_of = get_itemnumbers_of(@biblionumbers); - -Given a list of biblionumbers, return the list of corresponding itemnumbers -for each biblionumber. - -Return a reference on a hash where keys are biblionumbers and values are -references on array of itemnumbers. - -=back - -=cut - -sub get_itemnumbers_of { - my @biblionumbers = @_; - - my $dbh = C4::Context->dbh; - - my $query = ' - SELECT itemnumber, - biblionumber - FROM items - WHERE biblionumber IN (?' . ( ',?' x scalar @biblionumbers - 1 ) . ') - '; - my $sth = $dbh->prepare($query); - $sth->execute(@biblionumbers); - - my %itemnumbers_of; - - while ( my ( $itemnumber, $biblionumber ) = $sth->fetchrow_array ) { - push @{ $itemnumbers_of{$biblionumber} }, $itemnumber; - } - - return \%itemnumbers_of; -} - -=head2 GetItemInfosOf - -=over 4 - -GetItemInfosOf(@itemnumbers); - -=back - -=cut - -sub GetItemInfosOf { - my @itemnumbers = @_; - - my $query = ' - SELECT * - FROM items - WHERE itemnumber IN (' . join( ',', @itemnumbers ) . ') - '; - return get_infos_of( $query, 'itemnumber' ); -} - -=head2 GetItemsByBiblioitemnumber - -=over 4 - -GetItemsByBiblioitemnumber($biblioitemnumber); - -Returns an arrayref of hashrefs suitable for use in a TMPL_LOOP -Called by moredetail.pl - -=back - -=cut - -sub GetItemsByBiblioitemnumber { - my ( $bibitem ) = @_; - my $dbh = C4::Context->dbh; - my $sth = $dbh->prepare("SELECT * FROM items WHERE items.biblioitemnumber = ?") || die $dbh->errstr; - # Get all items attached to a biblioitem - my $i = 0; - my @results; - $sth->execute($bibitem) || die $sth->errstr; - while ( my $data = $sth->fetchrow_hashref ) { - # Foreach item, get circulation information - my $sth2 = $dbh->prepare( "SELECT * FROM issues,borrowers - WHERE itemnumber = ? - AND returndate is NULL - AND issues.borrowernumber = borrowers.borrowernumber" - ); - $sth2->execute( $data->{'itemnumber'} ); - if ( my $data2 = $sth2->fetchrow_hashref ) { - # if item is out, set the due date and who it is out too - $data->{'date_due'} = $data2->{'date_due'}; - $data->{'cardnumber'} = $data2->{'cardnumber'}; - $data->{'borrowernumber'} = $data2->{'borrowernumber'}; - } - else { - # set date_due to blank, so in the template we check itemlost, and wthdrawn - $data->{'date_due'} = ''; - } # else - $sth2->finish; - # Find the last 3 people who borrowed this item. - my $query2 = "SELECT * FROM issues, borrowers WHERE itemnumber = ? - AND issues.borrowernumber = borrowers.borrowernumber - AND returndate is not NULL - ORDER BY returndate desc,timestamp desc LIMIT 3"; - $sth2 = $dbh->prepare($query2) || die $dbh->errstr; - $sth2->execute( $data->{'itemnumber'} ) || die $sth2->errstr; - my $i2 = 0; - while ( my $data2 = $sth2->fetchrow_hashref ) { - $data->{"timestamp$i2"} = $data2->{'timestamp'}; - $data->{"card$i2"} = $data2->{'cardnumber'}; - $data->{"borrower$i2"} = $data2->{'borrowernumber'}; - $i2++; - } - $sth2->finish; - push(@results,$data); - } - $sth->finish; - return (\@results); -} - - =head2 GetBiblioItemInfosOf =over 4 @@ -4187,25 +3593,6 @@ sub set_service_options { return $serviceOptions; } -=head2 GetItemsCount - -$count = &GetItemsCount( $biblionumber); -this function return count of item with $biblionumber -=cut - -sub GetItemsCount { - my ( $biblionumber ) = @_; - my $dbh = C4::Context->dbh; - my $query = "SELECT count(*) - FROM items - WHERE biblionumber=?"; - my $sth = $dbh->prepare($query); - $sth->execute($biblionumber); - my $count = $sth->fetchrow; - $sth->finish; - return ($count); -} - END { } # module clean-up code here (global destructor) 1; diff --git a/C4/Items.pm b/C4/Items.pm index e7f8e315b6..ca8d74f9ce 100644 --- a/C4/Items.pm +++ b/C4/Items.pm @@ -22,11 +22,13 @@ use strict; require Exporter; use C4::Context; +use C4::Koha; use C4::Biblio; -use C4::Dates; +use C4::Dates qw/format_date format_date_in_iso/; use MARC::Record; use C4::ClassSource; use C4::Log; +use C4::Reserves; use vars qw($VERSION @ISA @EXPORT); @@ -43,6 +45,16 @@ my $VERSION = 3.00; ModItem ModDateLastSeen ModItemTransfer + + GetItemStatus + GetItemLocation + GetLostItems + GetItemsForInventory + GetItemsCount + GetItemInfosOf + GetItemsByBiblioitemnumber + GetItemsInfo + get_itemnumbers_of ); =head1 NAME @@ -79,7 +91,7 @@ accurate. Most of the functions in C were originally in the C module. -=head1 EXPORTED FUNCTIONS +=head1 CORE EXPORTED FUNCTIONS The following functions are meant for use by users of C @@ -326,6 +338,662 @@ sub ModDateLastSeen { ModItem({ itemlost => 0, datelastseen => $today->output("iso") }, undef, $itemnumber); } +=head1 EXPORTED SPECIAL ACCESSOR FUNCTIONS + +The following functions provide various ways of +getting an item record, a set of item records, or +lists of authorized values for certain item fields. + +Some of the functions in this group are candidates +for refactoring -- for example, some of the code +in C and C +has copy-and-paste work. + +=cut + +=head2 GetItemStatus + +=over 4 + +$itemstatushash = GetItemStatus($fwkcode); + +=back + +Returns a list of valid values for the +C field. + +NOTE: does B return an individual item's +status. + +Can be MARC dependant. +fwkcode is optional. +But basically could be can be loan or not +Create a status selector with the following code + +=head3 in PERL SCRIPT + +=over 4 + +my $itemstatushash = getitemstatus; +my @itemstatusloop; +foreach my $thisstatus (keys %$itemstatushash) { + my %row =(value => $thisstatus, + statusname => $itemstatushash->{$thisstatus}->{'statusname'}, + ); + push @itemstatusloop, \%row; +} +$template->param(statusloop=>\@itemstatusloop); + +=back + +=head3 in TEMPLATE + +=over 4 + + + +=back + +=cut + +sub GetItemStatus { + + # returns a reference to a hash of references to status... + my ($fwk) = @_; + my %itemstatus; + my $dbh = C4::Context->dbh; + my $sth; + $fwk = '' unless ($fwk); + my ( $tag, $subfield ) = + GetMarcFromKohaField( "items.notforloan", $fwk ); + if ( $tag and $subfield ) { + my $sth = + $dbh->prepare( + "SELECT authorised_value + FROM marc_subfield_structure + WHERE tagfield=? + AND tagsubfield=? + AND frameworkcode=? + " + ); + $sth->execute( $tag, $subfield, $fwk ); + if ( my ($authorisedvaluecat) = $sth->fetchrow ) { + my $authvalsth = + $dbh->prepare( + "SELECT authorised_value,lib + FROM authorised_values + WHERE category=? + ORDER BY lib + " + ); + $authvalsth->execute($authorisedvaluecat); + while ( my ( $authorisedvalue, $lib ) = $authvalsth->fetchrow ) { + $itemstatus{$authorisedvalue} = $lib; + } + $authvalsth->finish; + return \%itemstatus; + exit 1; + } + else { + + #No authvalue list + # build default + } + $sth->finish; + } + + #No authvalue list + #build default + $itemstatus{"1"} = "Not For Loan"; + return \%itemstatus; +} + +=head2 GetItemLocation + +=over 4 + +$itemlochash = GetItemLocation($fwk); + +=back + +Returns a list of valid values for the +C field. + +NOTE: does B return an individual item's +location. + +where fwk stands for an optional framework code. +Create a location selector with the following code + +=head3 in PERL SCRIPT + +=over 4 + +my $itemlochash = getitemlocation; +my @itemlocloop; +foreach my $thisloc (keys %$itemlochash) { + my $selected = 1 if $thisbranch eq $branch; + my %row =(locval => $thisloc, + selected => $selected, + locname => $itemlochash->{$thisloc}, + ); + push @itemlocloop, \%row; +} +$template->param(itemlocationloop => \@itemlocloop); + +=back + +=head3 in TEMPLATE + +=over 4 + + + +=back + +=cut + +sub GetItemLocation { + + # returns a reference to a hash of references to location... + my ($fwk) = @_; + my %itemlocation; + my $dbh = C4::Context->dbh; + my $sth; + $fwk = '' unless ($fwk); + my ( $tag, $subfield ) = + GetMarcFromKohaField( "items.location", $fwk ); + if ( $tag and $subfield ) { + my $sth = + $dbh->prepare( + "SELECT authorised_value + FROM marc_subfield_structure + WHERE tagfield=? + AND tagsubfield=? + AND frameworkcode=?" + ); + $sth->execute( $tag, $subfield, $fwk ); + if ( my ($authorisedvaluecat) = $sth->fetchrow ) { + my $authvalsth = + $dbh->prepare( + "SELECT authorised_value,lib + FROM authorised_values + WHERE category=? + ORDER BY lib" + ); + $authvalsth->execute($authorisedvaluecat); + while ( my ( $authorisedvalue, $lib ) = $authvalsth->fetchrow ) { + $itemlocation{$authorisedvalue} = $lib; + } + $authvalsth->finish; + return \%itemlocation; + exit 1; + } + else { + + #No authvalue list + # build default + } + $sth->finish; + } + + #No authvalue list + #build default + $itemlocation{"1"} = "Not For Loan"; + return \%itemlocation; +} + +=head2 GetLostItems + +=over 4 + +$items = GetLostItems($where,$orderby); + +=back + +This function get the items lost into C<$items>. + +=over 2 + +=item input: +C<$where> is a hashref. it containts a field of the items table as key +and the value to match as value. +C<$orderby> is a field of the items table. + +=item return: +C<$items> is a reference to an array full of hasref which keys are items' table column. + +=item usage in the perl script: + +my %where; +$where{barcode} = 0001548; +my $items = GetLostItems( \%where, "homebranch" ); +$template->param(itemsloop => $items); + +=back + +=cut + +sub GetLostItems { + # Getting input args. + my $where = shift; + my $orderby = shift; + my $dbh = C4::Context->dbh; + + my $query = " + SELECT * + FROM items + WHERE itemlost IS NOT NULL + AND itemlost <> 0 + "; + foreach my $key (keys %$where) { + $query .= " AND " . $key . " LIKE '%" . $where->{$key} . "%'"; + } + $query .= " ORDER BY ".$orderby if defined $orderby; + + my $sth = $dbh->prepare($query); + $sth->execute; + my @items; + while ( my $row = $sth->fetchrow_hashref ){ + push @items, $row; + } + return \@items; +} + +=head2 GetItemsForInventory + +=over 4 + +$itemlist = GetItemsForInventory($minlocation,$maxlocation,$datelastseen,$offset,$size) + +=back + +Retrieve a list of title/authors/barcode/callnumber, for biblio inventory. + +The sub returns a list of hashes, containing itemnumber, author, title, barcode & item callnumber. +It is ordered by callnumber,title. + +The minlocation & maxlocation parameters are used to specify a range of item callnumbers +the datelastseen can be used to specify that you want to see items not seen since a past date only. +offset & size can be used to retrieve only a part of the whole listing (defaut behaviour) + +=cut + +sub GetItemsForInventory { + my ( $minlocation, $maxlocation,$location, $datelastseen, $branch, $offset, $size ) = @_; + my $dbh = C4::Context->dbh; + my $sth; + if ($datelastseen) { + $datelastseen=format_date_in_iso($datelastseen); + my $query = + "SELECT itemnumber,barcode,itemcallnumber,title,author,biblio.biblionumber,datelastseen + FROM items + LEFT JOIN biblio ON items.biblionumber=biblio.biblionumber + WHERE itemcallnumber>= ? + AND itemcallnumber <=? + AND (datelastseen< ? OR datelastseen IS NULL)"; + $query.= " AND items.location=".$dbh->quote($location) if $location; + $query.= " AND items.homebranch=".$dbh->quote($branch) if $branch; + $query .= " ORDER BY itemcallnumber,title"; + $sth = $dbh->prepare($query); + $sth->execute( $minlocation, $maxlocation, $datelastseen ); + } + else { + my $query =" + SELECT itemnumber,barcode,itemcallnumber,biblio.biblionumber,title,author,datelastseen + FROM items + LEFT JOIN biblio ON items.biblionumber=biblio.biblionumber + WHERE itemcallnumber>= ? + AND itemcallnumber <=?"; + $query.= " AND items.location=".$dbh->quote($location) if $location; + $query.= " AND items.homebranch=".$dbh->quote($branch) if $branch; + $query .= " ORDER BY itemcallnumber,title"; + $sth = $dbh->prepare($query); + $sth->execute( $minlocation, $maxlocation ); + } + my @results; + while ( my $row = $sth->fetchrow_hashref ) { + $offset-- if ($offset); + $row->{datelastseen}=format_date($row->{datelastseen}); + if ( ( !$offset ) && $size ) { + push @results, $row; + $size--; + } + } + return \@results; +} + +=head2 GetItemsCount + +=over 4 +$count = &GetItemsCount( $biblionumber); + +=back + +This function return count of item with $biblionumber + +=cut + +sub GetItemsCount { + my ( $biblionumber ) = @_; + my $dbh = C4::Context->dbh; + my $query = "SELECT count(*) + FROM items + WHERE biblionumber=?"; + my $sth = $dbh->prepare($query); + $sth->execute($biblionumber); + my $count = $sth->fetchrow; + $sth->finish; + return ($count); +} + +=head2 GetItemInfosOf + +=over 4 + +GetItemInfosOf(@itemnumbers); + +=back + +=cut + +sub GetItemInfosOf { + my @itemnumbers = @_; + + my $query = ' + SELECT * + FROM items + WHERE itemnumber IN (' . join( ',', @itemnumbers ) . ') + '; + return get_infos_of( $query, 'itemnumber' ); +} + +=head2 GetItemsByBiblioitemnumber + +=over 4 + +GetItemsByBiblioitemnumber($biblioitemnumber); + +=back + +Returns an arrayref of hashrefs suitable for use in a TMPL_LOOP +Called by C + +=cut + +sub GetItemsByBiblioitemnumber { + my ( $bibitem ) = @_; + my $dbh = C4::Context->dbh; + my $sth = $dbh->prepare("SELECT * FROM items WHERE items.biblioitemnumber = ?") || die $dbh->errstr; + # Get all items attached to a biblioitem + my $i = 0; + my @results; + $sth->execute($bibitem) || die $sth->errstr; + while ( my $data = $sth->fetchrow_hashref ) { + # Foreach item, get circulation information + my $sth2 = $dbh->prepare( "SELECT * FROM issues,borrowers + WHERE itemnumber = ? + AND returndate is NULL + AND issues.borrowernumber = borrowers.borrowernumber" + ); + $sth2->execute( $data->{'itemnumber'} ); + if ( my $data2 = $sth2->fetchrow_hashref ) { + # if item is out, set the due date and who it is out too + $data->{'date_due'} = $data2->{'date_due'}; + $data->{'cardnumber'} = $data2->{'cardnumber'}; + $data->{'borrowernumber'} = $data2->{'borrowernumber'}; + } + else { + # set date_due to blank, so in the template we check itemlost, and wthdrawn + $data->{'date_due'} = ''; + } # else + $sth2->finish; + # Find the last 3 people who borrowed this item. + my $query2 = "SELECT * FROM issues, borrowers WHERE itemnumber = ? + AND issues.borrowernumber = borrowers.borrowernumber + AND returndate is not NULL + ORDER BY returndate desc,timestamp desc LIMIT 3"; + $sth2 = $dbh->prepare($query2) || die $dbh->errstr; + $sth2->execute( $data->{'itemnumber'} ) || die $sth2->errstr; + my $i2 = 0; + while ( my $data2 = $sth2->fetchrow_hashref ) { + $data->{"timestamp$i2"} = $data2->{'timestamp'}; + $data->{"card$i2"} = $data2->{'cardnumber'}; + $data->{"borrower$i2"} = $data2->{'borrowernumber'}; + $i2++; + } + $sth2->finish; + push(@results,$data); + } + $sth->finish; + return (\@results); +} + +=head2 GetItemsInfo + +=over 4 + +@results = GetItemsInfo($biblionumber, $type); + +=back + +Returns information about books with the given biblionumber. + +C<$type> may be either C or anything else. If it is not set to +C, then the search will exclude lost, very overdue, and +withdrawn items. + +C returns a list of references-to-hash. Each element +contains a number of keys. Most of them are table items from the +C, C, C, and C tables in the +Koha database. Other keys include: + +=over 2 + +=item C<$data-E{branchname}> + +The name (not the code) of the branch to which the book belongs. + +=item C<$data-E{datelastseen}> + +This is simply C, except that while the date is +stored in YYYY-MM-DD format in the database, here it is converted to +DD/MM/YYYY format. A NULL date is returned as C. + +=item C<$data-E{datedue}> + +=item C<$data-E{class}> + +This is the concatenation of C, the book's +Dewey code, and C. + +=item C<$data-E{ocount}> + +I think this is the number of copies of the book available. + +=item C<$data-E{order}> + +If this is set, it is set to C. + +=back + +=cut + +sub GetItemsInfo { + my ( $biblionumber, $type ) = @_; + my $dbh = C4::Context->dbh; + my $query = "SELECT *,items.notforloan as itemnotforloan + FROM items + LEFT JOIN biblio ON biblio.biblionumber = items.biblionumber + LEFT JOIN biblioitems ON biblioitems.biblioitemnumber = items.biblioitemnumber"; + $query .= (C4::Context->preference('item-level_itypes')) ? + " LEFT JOIN itemtypes on items.itype = itemtypes.itemtype " + : " LEFT JOIN itemtypes on biblioitems.itemtype = itemtypes.itemtype "; + $query .= "WHERE items.biblionumber = ? ORDER BY items.dateaccessioned desc" ; + my $sth = $dbh->prepare($query); + $sth->execute($biblionumber); + my $i = 0; + my @results; + my ( $date_due, $count_reserves ); + + my $isth = $dbh->prepare( + "SELECT issues.*,borrowers.cardnumber,borrowers.surname,borrowers.firstname,borrowers.branchcode as bcode + FROM issues LEFT JOIN borrowers ON issues.borrowernumber=borrowers.borrowernumber + WHERE itemnumber = ? + AND returndate IS NULL" + ); + while ( my $data = $sth->fetchrow_hashref ) { + my $datedue = ''; + $isth->execute( $data->{'itemnumber'} ); + if ( my $idata = $isth->fetchrow_hashref ) { + $data->{borrowernumber} = $idata->{borrowernumber}; + $data->{cardnumber} = $idata->{cardnumber}; + $data->{surname} = $idata->{surname}; + $data->{firstname} = $idata->{firstname}; + $datedue = $idata->{'date_due'}; + if (C4::Context->preference("IndependantBranches")){ + my $userenv = C4::Context->userenv; + if ( ($userenv) && ( $userenv->{flags} != 1 ) ) { + $data->{'NOTSAMEBRANCH'} = 1 if ($idata->{'bcode'} ne $userenv->{branch}); + } + } + } + if ( $datedue eq '' ) { + my ( $restype, $reserves ) = + C4::Reserves::CheckReserves( $data->{'itemnumber'} ); + if ($restype) { + $count_reserves = $restype; + } + } + $isth->finish; + + #get branch information..... + my $bsth = $dbh->prepare( + "SELECT * FROM branches WHERE branchcode = ? + " + ); + $bsth->execute( $data->{'holdingbranch'} ); + if ( my $bdata = $bsth->fetchrow_hashref ) { + $data->{'branchname'} = $bdata->{'branchname'}; + } + $data->{'datedue'} = $datedue; + $data->{'count_reserves'} = $count_reserves; + + # get notforloan complete status if applicable + my $sthnflstatus = $dbh->prepare( + 'SELECT authorised_value + FROM marc_subfield_structure + WHERE kohafield="items.notforloan" + ' + ); + + $sthnflstatus->execute; + my ($authorised_valuecode) = $sthnflstatus->fetchrow; + if ($authorised_valuecode) { + $sthnflstatus = $dbh->prepare( + "SELECT lib FROM authorised_values + WHERE category=? + AND authorised_value=?" + ); + $sthnflstatus->execute( $authorised_valuecode, + $data->{itemnotforloan} ); + my ($lib) = $sthnflstatus->fetchrow; + $data->{notforloan} = $lib; + } + + # my stack procedures + my $stackstatus = $dbh->prepare( + 'SELECT authorised_value + FROM marc_subfield_structure + WHERE kohafield="items.stack" + ' + ); + $stackstatus->execute; + + ($authorised_valuecode) = $stackstatus->fetchrow; + if ($authorised_valuecode) { + $stackstatus = $dbh->prepare( + "SELECT lib + FROM authorised_values + WHERE category=? + AND authorised_value=? + " + ); + $stackstatus->execute( $authorised_valuecode, $data->{stack} ); + my ($lib) = $stackstatus->fetchrow; + $data->{stack} = $lib; + } + # Find the last 3 people who borrowed this item. + my $sth2 = $dbh->prepare("SELECT * FROM issues,borrowers + WHERE itemnumber = ? + AND issues.borrowernumber = borrowers.borrowernumber + AND returndate IS NOT NULL LIMIT 3"); + $sth2->execute($data->{'itemnumber'}); + my $ii = 0; + while (my $data2 = $sth2->fetchrow_hashref()) { + $data->{"timestamp$ii"} = $data2->{'timestamp'} if $data2->{'timestamp'}; + $data->{"card$ii"} = $data2->{'cardnumber'} if $data2->{'cardnumber'}; + $data->{"borrower$ii"} = $data2->{'borrowernumber'} if $data2->{'borrowernumber'}; + $ii++; + } + + $results[$i] = $data; + $i++; + } + $sth->finish; + + return (@results); +} + +=head2 get_itemnumbers_of + +=over 4 + +my @itemnumbers_of = get_itemnumbers_of(@biblionumbers); + +=back + +Given a list of biblionumbers, return the list of corresponding itemnumbers +for each biblionumber. + +Return a reference on a hash where keys are biblionumbers and values are +references on array of itemnumbers. + +=cut + +sub get_itemnumbers_of { + my @biblionumbers = @_; + + my $dbh = C4::Context->dbh; + + my $query = ' + SELECT itemnumber, + biblionumber + FROM items + WHERE biblionumber IN (?' . ( ',?' x scalar @biblionumbers - 1 ) . ') + '; + my $sth = $dbh->prepare($query); + $sth->execute(@biblionumbers); + + my %itemnumbers_of; + + while ( my ( $itemnumber, $biblionumber ) = $sth->fetchrow_array ) { + push @{ $itemnumbers_of{$biblionumber} }, $itemnumber; + } + + return \%itemnumbers_of; +} + =head1 LIMITED USE FUNCTIONS The following functions, while part of the public API, diff --git a/C4/XISBN.pm b/C4/XISBN.pm index 6288f5884d..4229d0d979 100644 --- a/C4/XISBN.pm +++ b/C4/XISBN.pm @@ -20,6 +20,7 @@ package C4::XISBN; use XML::Simple; #use LWP::Simple; use C4::Biblio; +use C4::Items; use LWP::UserAgent; use HTTP::Request::Common; diff --git a/catalogue/ISBDdetail.pl b/catalogue/ISBDdetail.pl index 4b70d0f91f..4360f0cd7e 100755 --- a/catalogue/ISBDdetail.pl +++ b/catalogue/ISBDdetail.pl @@ -42,6 +42,7 @@ use C4::Output; use CGI; use C4::Koha; use C4::Biblio; +use C4::Items; use C4::Branch; # GetBranchDetail use C4::Serials; # CountSubscriptionFromBiblionumber diff --git a/catalogue/MARCdetail.pl b/catalogue/MARCdetail.pl index d5e507b089..3919c488e3 100755 --- a/catalogue/MARCdetail.pl +++ b/catalogue/MARCdetail.pl @@ -52,6 +52,7 @@ use CGI; use C4::Koha; use MARC::Record; use C4::Biblio; +use C4::Items; use C4::Acquisition; use C4::Serials; #uses getsubscriptionsfrombiblionumber GetSubscriptionsFromBiblionumber diff --git a/catalogue/detail.pl b/catalogue/detail.pl index df1a7b971b..e2d4623008 100755 --- a/catalogue/detail.pl +++ b/catalogue/detail.pl @@ -25,6 +25,7 @@ use C4::Koha; use C4::Serials; #uses getsubscriptionfrom biblionumber use C4::Output; use C4::Biblio; +use C4::Items; use C4::Circulation; use C4::Branch; use C4::Reserves; diff --git a/catalogue/detailprint.pl b/catalogue/detailprint.pl index 6c4202d408..00c0863cd5 100755 --- a/catalogue/detailprint.pl +++ b/catalogue/detailprint.pl @@ -23,6 +23,7 @@ use C4::Context; use CGI; use C4::Auth; use C4::Biblio; +use C4::Items; use C4::Output; use C4::Dates; diff --git a/catalogue/moredetail.pl b/catalogue/moredetail.pl index 4e127905ae..8b06517ad3 100755 --- a/catalogue/moredetail.pl +++ b/catalogue/moredetail.pl @@ -23,6 +23,7 @@ require Exporter; use C4::Koha; use CGI; use C4::Biblio; +use C4::Items; use C4::Branch; use C4::Acquisition; use C4::Output; # contains gettemplate diff --git a/opac/opac-basket.pl b/opac/opac-basket.pl index b01d449f10..8c194b3ae3 100755 --- a/opac/opac-basket.pl +++ b/opac/opac-basket.pl @@ -20,6 +20,7 @@ use strict; require Exporter; use CGI; use C4::Biblio; +use C4::Items; use C4::Auth; use C4::Output; diff --git a/opac/opac-detail.pl b/opac/opac-detail.pl index bb4f146cd0..ddb42b847a 100755 --- a/opac/opac-detail.pl +++ b/opac/opac-detail.pl @@ -26,6 +26,7 @@ use C4::Koha; use C4::Serials; #uses getsubscriptionfrom biblionumber use C4::Output; use C4::Biblio; +use C4::Items; use C4::Dates qw/format_date/; use C4::XISBN qw(get_xisbns get_biblio_from_xisbn); use C4::Amazon; diff --git a/opac/opac-sendbasket.pl b/opac/opac-sendbasket.pl index 44305fc0cb..f959fbf348 100755 --- a/opac/opac-sendbasket.pl +++ b/opac/opac-sendbasket.pl @@ -22,6 +22,7 @@ use Mail::Sendmail; use MIME::QuotedPrint; use MIME::Base64; use C4::Biblio; +use C4::Items; use C4::Auth; use C4::Output; use C4::Biblio; diff --git a/reports/itemslost.pl b/reports/itemslost.pl index 844b240c91..0d87d9e73f 100755 --- a/reports/itemslost.pl +++ b/reports/itemslost.pl @@ -26,7 +26,8 @@ use strict; use CGI; use C4::Auth; use C4::Output; -use C4::Biblio; # GetLostItems +use C4::Biblio; +use C4::Items; use C4::Koha; # GetItemTypes use C4::Branch; # GetBranches diff --git a/reports/reservereport.pl b/reports/reservereport.pl index d67320b596..fa389647f6 100755 --- a/reports/reservereport.pl +++ b/reports/reservereport.pl @@ -31,6 +31,7 @@ use C4::Output; use C4::Branch; # GetBranches use C4::Auth; use C4::Koha; +use C4::Items; my $input = new CGI; @@ -94,7 +95,7 @@ for ( my $i = 0 ; $i < $count ; $i++ ) { # FIXME still need to shift the text to the template so its translateable if ( $data->[$i]) { # find if its on issue - my @items = &GetItemsInfo($line{'biblionumber'}, 'intra' ); + my @items = GetItemsInfo($line{'biblionumber'}, 'intra' ); my $onissue = 0; foreach my $item (@items) { if ( $item->{'datedue'} eq 'Reserved' ) { diff --git a/reserve/request.pl b/reserve/request.pl index d0fea987e9..452e80df2a 100755 --- a/reserve/request.pl +++ b/reserve/request.pl @@ -34,6 +34,7 @@ use C4::Output; use C4::Auth; use C4::Reserves; use C4::Biblio; +use C4::Items; use C4::Koha; use C4::Circulation; use C4::Dates qw/format_date/; diff --git a/serials/routing-preview.pl b/serials/routing-preview.pl index 9f11ec7a1a..3cc56776ad 100755 --- a/serials/routing-preview.pl +++ b/serials/routing-preview.pl @@ -15,6 +15,7 @@ use C4::Circulation; use C4::Context; use C4::Members; use C4::Biblio; +use C4::Items; use C4::Serials; my $query = new CGI; diff --git a/serials/serials-recieve.pl b/serials/serials-recieve.pl index 55c6be2fb2..89e86be052 100755 --- a/serials/serials-recieve.pl +++ b/serials/serials-recieve.pl @@ -67,6 +67,7 @@ use CGI; use C4::Auth; use C4::Dates qw/format_date format_date_in_iso/; use C4::Biblio; +use C4::Items; use C4::Koha; use C4::Output; use C4::Context; -- 2.39.5