additional cleanup in GetItemsInfo()
[koha.git] / C4 / Items.pm
index 1f92491..6c58365 100644 (file)
@@ -224,6 +224,12 @@ sub AddItem {
     _set_derived_columns_for_add($item);
     $item->{'more_subfields_xml'} = _get_unlinked_subfields_xml($unlinked_item_subfields);
     # FIXME - checks here
+    unless ( $item->{itype} ) {  # default to biblioitem.itemtype if no itype
+        my $itype_sth = $dbh->prepare("SELECT itemtype FROM biblioitems WHERE biblionumber = ?");
+        $itype_sth->execute( $item->{'biblionumber'} );
+        ( $item->{'itype'} ) = $itype_sth->fetchrow_array;
+    }
+
        my ( $itemnumber, $error ) = _koha_new_item( $item, $item->{barcode} );
     $item->{'itemnumber'} = $itemnumber;
 
@@ -927,23 +933,24 @@ sub GetLostItems {
 
     my $query   = "
         SELECT *
-        FROM   items, biblio, authorised_values
+        FROM   items
+            LEFT JOIN biblio ON (items.biblionumber = biblio.biblionumber)
+            LEFT JOIN biblioitems ON (items.biblionumber = biblioitems.biblionumber)
+            LEFT JOIN authorised_values ON (items.itemlost = authorised_values.authorised_value)
         WHERE
-                       items.biblionumber = biblio.biblionumber
-                       AND items.itemlost = authorised_values.authorised_value
-                       AND authorised_values.category = 'LOST'
+               authorised_values.category = 'LOST'
                AND itemlost IS NOT NULL
                AND itemlost <> 0
-          
     ";
     my @query_parameters;
     foreach my $key (keys %$where) {
         $query .= " AND $key LIKE ?";
         push @query_parameters, "%$where->{$key}%";
     }
-    if ( defined $orderby ) {
-        $query .= ' ORDER BY ?';
-        push @query_parameters, $orderby;
+    my @ordervalues = qw/title author homebranch itype barcode price replacementprice lib datelastseen location/;
+    
+    if ( defined $orderby && grep($orderby, @ordervalues)) {
+        $query .= ' ORDER BY '.$orderby;
     }
 
     my $sth = $dbh->prepare($query);
@@ -976,40 +983,57 @@ offset & size can be used to retrieve only a part of the whole listing (defaut b
 =cut
 
 sub GetItemsForInventory {
-    my ( $minlocation, $maxlocation,$location, $itemtype, $datelastseen, $branch, $offset, $size ) = @_;
+    my ( $minlocation, $maxlocation,$location, $itemtype, $ignoreissued, $datelastseen, $branch, $offset, $size ) = @_;
     my $dbh = C4::Context->dbh;
+    my ( @bind_params, @where_strings );
 
     my $query = <<'END_SQL';
-SELECT itemnumber, barcode, itemcallnumber, title, author, biblio.biblionumber, datelastseen
+SELECT items.itemnumber, barcode, itemcallnumber, title, author, biblio.biblionumber, datelastseen
 FROM items
   LEFT JOIN biblio ON items.biblionumber = biblio.biblionumber
   LEFT JOIN biblioitems on items.biblionumber = biblioitems.biblionumber
-WHERE itemcallnumber >= ?
-  AND itemcallnumber <= ?
 END_SQL
-    my @bind_params = ( $minlocation, $maxlocation );
+
+    if ($minlocation) {
+        push @where_strings, 'itemcallnumber >= ?';
+        push @bind_params, $minlocation;
+    }
+
+    if ($maxlocation) {
+        push @where_strings, 'itemcallnumber <= ?';
+        push @bind_params, $maxlocation;
+    }
 
     if ($datelastseen) {
         $datelastseen = format_date_in_iso($datelastseen);  
-        $query .= ' AND (datelastseen < ? OR datelastseen IS NULL) ';
+        push @where_strings, '(datelastseen < ? OR datelastseen IS NULL)';
         push @bind_params, $datelastseen;
     }
 
     if ( $location ) {
-        $query.= ' AND items.location = ? ';
+        push @where_strings, 'items.location = ?';
         push @bind_params, $location;
     }
     
     if ( $branch ) {
-        $query.= ' AND items.homebranch = ? ';
+        push @where_strings, 'items.homebranch = ?';
         push @bind_params, $branch;
     }
     
     if ( $itemtype ) {
-        $query.= ' AND biblioitems.itemtype = ? ';
+        push @where_strings, 'biblioitems.itemtype = ?';
         push @bind_params, $itemtype;
     }
 
+    if ( $ignoreissued) {
+        $query .= "LEFT JOIN issues ON items.itemnumber = issues.itemnumber ";
+        push @where_strings, 'issues.date_due IS NULL';
+    }
+
+    if ( @where_strings ) {
+        $query .= 'WHERE ';
+        $query .= join ' AND ', @where_strings;
+    }
     $query .= ' ORDER BY itemcallnumber, title';
     my $sth = $dbh->prepare($query);
     $sth->execute( @bind_params );
@@ -1184,19 +1208,34 @@ If this is set, it is set to C<One Order>.
 sub GetItemsInfo {
     my ( $biblionumber, $type ) = @_;
     my $dbh   = C4::Context->dbh;
-    my $query = "SELECT items.*,biblio.*,biblioitems.volume,biblioitems.number,biblioitems.itemtype,biblioitems.isbn,biblioitems.issn,biblioitems.publicationyear,biblioitems.publishercode,biblioitems.volumedate,biblioitems.volumedesc,biblioitems.lccn,biblioitems.url,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" ;
+    # note biblioitems.* must be avoided to prevent large marc and marcxml fields from killing performance.
+    my $query = "
+    SELECT items.*,
+           biblio.*,
+           biblioitems.volume,
+           biblioitems.number,
+           biblioitems.itemtype,
+           biblioitems.isbn,
+           biblioitems.issn,
+           biblioitems.publicationyear,
+           biblioitems.publishercode,
+           biblioitems.volumedate,
+           biblioitems.volumedesc,
+           biblioitems.lccn,
+           biblioitems.url,
+           items.notforloan as itemnotforloan,
+           itemtypes.description
+     FROM items
+     LEFT JOIN biblio      ON      biblio.biblionumber     = items.biblionumber
+     LEFT JOIN biblioitems ON biblioitems.biblioitemnumber = items.biblioitemnumber
+     LEFT JOIN itemtypes   ON   itemtypes.itemtype         = "
+     . (C4::Context->preference('item-level_itypes') ? 'items.itype' : 'biblioitems.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, $serial );
+    my $serial;
 
     my $isth    = $dbh->prepare(
         "SELECT issues.*,borrowers.cardnumber,borrowers.surname,borrowers.firstname,borrowers.branchcode as bcode
@@ -1206,6 +1245,7 @@ sub GetItemsInfo {
        my $ssth = $dbh->prepare("SELECT serialseq,publisheddate from serialitems left join serial on serialitems.serialid=serial.serialid where serialitems.itemnumber=? "); 
        while ( my $data = $sth->fetchrow_hashref ) {
         my $datedue = '';
+        my $count_reserves;
         $isth->execute( $data->{'itemnumber'} );
         if ( my $idata = $isth->fetchrow_hashref ) {
             $data->{borrowernumber} = $idata->{borrowernumber};
@@ -1215,7 +1255,7 @@ sub GetItemsInfo {
             $datedue                = $idata->{'date_due'};
         if (C4::Context->preference("IndependantBranches")){
         my $userenv = C4::Context->userenv;
-        if ( ($userenv) && ( $userenv->{flags} != 1 ) ) { 
+        if ( ($userenv) && ( $userenv->{flags} % 2 != 1 ) ) { 
             $data->{'NOTSAMEBRANCH'} = 1 if ($idata->{'bcode'} ne $userenv->{branch});
         }
         }
@@ -1228,9 +1268,10 @@ sub GetItemsInfo {
                if ( $datedue eq '' ) {
             my ( $restype, $reserves ) =
               C4::Reserves::CheckReserves( $data->{'itemnumber'} );
-            if ($restype) {
-                $count_reserves = $restype;
-            }
+# Previous conditional check with if ($restype) is not needed because a true
+# result for one item will result in subsequent items defaulting to this true
+# value.
+            $count_reserves = $restype;
         }
         $isth->finish;
         $ssth->finish;
@@ -1295,6 +1336,7 @@ sub GetItemsInfo {
         my $sth2 = $dbh->prepare("SELECT * FROM old_issues,borrowers
                                     WHERE itemnumber = ?
                                     AND old_issues.borrowernumber = borrowers.borrowernumber
+                                    ORDER BY returndate DESC
                                     LIMIT 3");
         $sth2->execute($data->{'itemnumber'});
         my $ii = 0;
@@ -1308,7 +1350,6 @@ sub GetItemsInfo {
         $results[$i] = $data;
         $i++;
     }
-    $sth->finish;
        if($serial) {
                return( sort { ($b->{'publisheddate'} || $b->{'enumchron'}) cmp ($a->{'publisheddate'} || $a->{'enumchron'}) } @results );
        } else {
@@ -1520,7 +1561,11 @@ sub GetMarcItem {
 
     # Tack on 'items.' prefix to column names so that TransformKohaToMarc will work.
     # Also, don't emit a subfield if the underlying field is blank.
-    my $mungeditem = { map {  $itemrecord->{$_} ne '' ? ("items.$_" => $itemrecord->{$_}) : ()  } keys %{ $itemrecord } };
+    my $mungeditem = { 
+        map {  
+            defined($itemrecord->{$_}) && $itemrecord->{$_} ne '' ? ("items.$_" => $itemrecord->{$_}) : ()  
+        } keys %{ $itemrecord } 
+    };
     my $itemmarc = TransformKohaToMarc($mungeditem);
 
     my $unlinked_item_subfields = _parse_unlinked_item_subfields_from_xml($mungeditem->{'items.more_subfields_xml'});
@@ -1769,20 +1814,8 @@ C<items.wthdrawn>
 
 sub _set_defaults_for_add {
     my $item = shift;
-
-    # if dateaccessioned is provided, use it. Otherwise, set to NOW()
-    if (!(exists $item->{'dateaccessioned'}) || 
-         ($item->{'dateaccessioned'} eq '')) {
-        # FIXME add check for invalid date
-        my $today = C4::Dates->new();    
-        $item->{'dateaccessioned'} =  $today->output("iso"); #TODO: check time issues
-    }
-
-    # various item status fields cannot be null
-    $item->{'notforloan'} = 0 unless exists $item->{'notforloan'} and defined $item->{'notforloan'} and $item->{'notforloan'} ne '';
-    $item->{'damaged'}    = 0 unless exists $item->{'damaged'}    and defined $item->{'damaged'}    and $item->{'damaged'} ne '';
-    $item->{'itemlost'}   = 0 unless exists $item->{'itemlost'}   and defined $item->{'itemlost'}   and $item->{'itemlost'} ne '';
-    $item->{'wthdrawn'}   = 0 unless exists $item->{'wthdrawn'}   and defined $item->{'wthdrawn'}   and $item->{'wthdrawn'} ne '';
+    $item->{dateaccessioned} ||= C4::Dates->new->output('iso');
+    $item->{$_} ||= 0 for (qw( notforloan damaged itemlost wthdrawn));
 }
 
 =head2 _koha_new_item