Bug 10798: (follow-up) replace tabs by spaces
[koha_fer] / C4 / Items.pm
index 8116c22..c183644 100644 (file)
@@ -31,8 +31,10 @@ use C4::ClassSource;
 use C4::Log;
 use List::MoreUtils qw/any/;
 use YAML qw/Load/;
+use DateTime::Format::MySQL;
 use Data::Dumper; # used as part of logging item record changes, not just for
                   # debugging; so please don't remove this
+use Koha::DateUtils qw/dt_from_string/;
 
 use vars qw($VERSION @ISA @EXPORT);
 
@@ -145,6 +147,7 @@ sub GetItem {
     my ($itemnumber,$barcode, $serial) = @_;
     my $dbh = C4::Context->dbh;
        my $data;
+
     if ($itemnumber) {
         my $sth = $dbh->prepare("
             SELECT * FROM items 
@@ -159,6 +162,9 @@ sub GetItem {
         $sth->execute($barcode);               
         $data = $sth->fetchrow_hashref;
     }
+
+    return unless ( $data );
+
     if ( $serial) {      
     my $ssth = $dbh->prepare("SELECT serialseq,publisheddate from serialitems left join serial on serialitems.serialid=serial.serialid where serialitems.itemnumber=?");
         $ssth->execute($data->{'itemnumber'}) ;
@@ -536,6 +542,31 @@ sub ModItem {
 
     $item->{onloan} = undef if $item->{itemlost};
 
+    my @fields = qw( itemlost withdrawn );
+
+    # Only call GetItem if we need to set an "on" date field
+    if ( $item->{itemlost} || $item->{withdrawn} ) {
+        my $pre_mod_item = GetItem( $item->{'itemnumber'} );
+        for my $field (@fields) {
+            if (    defined( $item->{$field} )
+                and not $pre_mod_item->{$field}
+                and $item->{$field} )
+            {
+                $item->{ $field . '_on' } =
+                  DateTime::Format::MySQL->format_datetime( dt_from_string() );
+            }
+        }
+    }
+
+    # If the field is defined but empty, we are removing and,
+    # and thus need to clear out the 'on' field as well
+    for my $field (@fields) {
+        if ( defined( $item->{$field} ) && !$item->{$field} ) {
+            $item->{ $field . '_on' } = undef;
+        }
+    }
+
+
     _set_derived_columns_for_mod($item);
     _do_column_fixes_for_mod($item);
     # FIXME add checks
@@ -552,7 +583,7 @@ sub ModItem {
     # item status is possible
     ModZebra( $biblionumber, "specialUpdate", "biblioserver" );
 
-    logaction("CATALOGUING", "MODIFY", $itemnumber, Dumper($item)) if C4::Context->preference("CataloguingLog");
+    logaction("CATALOGUING", "MODIFY", $itemnumber, "item ".Dumper($item)) if C4::Context->preference("CataloguingLog");
 }
 
 =head2 ModItemTransfer
@@ -618,11 +649,6 @@ sub DelItem {
     my $record = GetMarcBiblio($biblionumber);
     ModZebra( $biblionumber, "specialUpdate", "biblioserver" );
 
-    # backup the record
-    my $copy2deleted = $dbh->prepare("UPDATE deleteditems SET marc=? WHERE itemnumber=?");
-    $copy2deleted->execute( $record->as_usmarc(), $itemnumber );
-    # This last update statement makes that the timestamp column in deleteditems is updated too. If you remove these lines, please add a line to update the timestamp separately. See Bugzilla report 7146 and Biblio.pm (DelBiblio).
-
     #search item field code
     logaction("CATALOGUING", "DELETE", $itemnumber, "item") if C4::Context->preference("CataloguingLog");
 }
@@ -975,9 +1001,7 @@ sub GetLostItems {
 
 =head2 GetItemsForInventory
 
-  $itemlist = GetItemsForInventory($minlocation, $maxlocation, 
-                 $location, $itemtype $datelastseen, $branch, 
-                 $offset, $size, $statushash);
+($itemlist, $iTotalRecords)  = GetItemsForInventory($minlocation, $maxlocation, $location, $itemtype, $ignoreissued, $datelastseen, $branchcode, $offset, $size, $statushash);
 
 Retrieve a list of title/authors/barcode/callnumber, for biblio inventory.
 
@@ -990,6 +1014,8 @@ the datelastseen can be used to specify that you want to see items not seen sinc
 offset & size can be used to retrieve only a part of the whole listing (defaut behaviour)
 $statushash requires a hashref that has the authorized values fieldname (intems.notforloan, etc...) as keys, and an arrayref of statuscodes we are searching for as values.
 
+$iTotalRecords is the number of rows that would have been returned without the $offset, $size limit clause
+
 =cut
 
 sub GetItemsForInventory {
@@ -997,12 +1023,15 @@ sub GetItemsForInventory {
     my $dbh = C4::Context->dbh;
     my ( @bind_params, @where_strings );
 
-    my $query = <<'END_SQL';
-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
-END_SQL
+    my $select_columns = q{
+        SELECT items.itemnumber, barcode, itemcallnumber, title, author, biblio.biblionumber, biblio.frameworkcode, datelastseen, homebranch, location, notforloan, damaged, itemlost, stocknumber
+    };
+    my $select_count = q{SELECT COUNT(*)};
+    my $query = q{
+        FROM items
+        LEFT JOIN biblio ON items.biblionumber = biblio.biblionumber
+        LEFT JOIN biblioitems on items.biblionumber = biblioitems.biblionumber
+    };
     if ($statushash){
         for my $authvfield (keys %$statushash){
             if ( scalar @{$statushash->{$authvfield}} > 0 ){
@@ -1041,7 +1070,7 @@ END_SQL
         }
         push @bind_params, $branchcode;
     }
-    
+
     if ( $itemtype ) {
         push @where_strings, 'biblioitems.itemtype = ?';
         push @bind_params, $itemtype;
@@ -1057,20 +1086,34 @@ END_SQL
         $query .= join ' AND ', @where_strings;
     }
     $query .= ' ORDER BY items.cn_sort, itemcallnumber, title';
+    my $count_query = $select_count . $query;
+    $query .= " LIMIT $offset, $size" if ($offset and $size);
+    $query = $select_columns . $query;
     my $sth = $dbh->prepare($query);
     $sth->execute( @bind_params );
 
-    my @results;
-    $size--;
-    while ( my $row = $sth->fetchrow_hashref ) {
-        $offset-- if ($offset);
-        $row->{datelastseen}=format_date($row->{datelastseen});
-        if ( ( !$offset ) && $size ) {
-            push @results, $row;
-            $size--;
+    my @results = ();
+    my $tmpresults = $sth->fetchall_arrayref({});
+    $sth = $dbh->prepare( $count_query );
+    $sth->execute( @bind_params );
+    my ($iTotalRecords) = $sth->fetchrow_array();
+
+    foreach my $row (@$tmpresults) {
+
+        # Auth values
+        foreach (keys %$row) {
+            # If the koha field is mapped to a marc field
+            my ($f, $sf) = GetMarcFromKohaField("items.$_", $row->{'frameworkcode'});
+            if ($f and $sf) {
+                # We replace the code with it's description
+                my $authvals = C4::Koha::GetKohaAuthorisedValuesFromField($f, $sf, $row->{'frameworkcode'});
+                $row->{$_} = $authvals->{$row->{$_}} if defined $authvals->{$row->{$_}};
+            }
         }
+        push @results, $row;
     }
-    return \@results;
+
+    return (\@results, $iTotalRecords);
 }
 
 =head2 GetItemsCount
@@ -1260,7 +1303,7 @@ sub GetItemsInfo {
             $datedue                = $idata->{'date_due'};
         if (C4::Context->preference("IndependentBranches")){
         my $userenv = C4::Context->userenv;
-        if ( ($userenv) && ( $userenv->{flags} % 2 != 1 ) ) { 
+        unless ( C4::Context->IsSuperLibrarian() ) {
             $data->{'NOTSAMEBRANCH'} = 1 if ($idata->{'bcode'} ne $userenv->{branch});
         }
         }
@@ -2210,16 +2253,19 @@ sub DelItemCheck {
 
 
     # check that there is no issue on this item before deletion.
-    my $sth=$dbh->prepare("select * from issues i where i.itemnumber=?");
+    my $sth = $dbh->prepare(q{
+        SELECT COUNT(*) FROM issues
+        WHERE itemnumber = ?
+    });
     $sth->execute($itemnumber);
+    my ($onloan) = $sth->fetchrow;
 
     my $item = GetItem($itemnumber);
-    my $onloan=$sth->fetchrow;
 
     if ($onloan){
         $error = "book_on_loan" 
     }
-    elsif ( !( C4::Context->userenv->{flags} & 1 )
+    elsif ( !C4::Context->IsSuperLibrarian()
         and C4::Context->preference("IndependentBranches")
         and ( C4::Context->userenv->{branch} ne $item->{'homebranch'} ) )
     {
@@ -2227,9 +2273,13 @@ sub DelItemCheck {
     }
        else{
         # check it doesnt have a waiting reserve
-        $sth=$dbh->prepare("SELECT * FROM reserves WHERE (found = 'W' or found = 'T') AND itemnumber = ?");
+        $sth = $dbh->prepare(q{
+            SELECT COUNT(*) FROM reserves
+            WHERE (found = 'W' OR found = 'T')
+            AND itemnumber = ?
+        });
         $sth->execute($itemnumber);
-        my $reserve=$sth->fetchrow;
+        my ($reserve) = $sth->fetchrow;
         if ($reserve){
             $error = "book_reserved";
         } elsif ($countanalytics > 0){
@@ -2266,10 +2316,10 @@ sub _koha_modify_item {
     $query =~ s/,$//;
     $query .= " WHERE itemnumber=?";
     push @bind, $item->{'itemnumber'};
-    my $sth = C4::Context->dbh->prepare($query);
+    my $sth = $dbh->prepare($query);
     $sth->execute(@bind);
-    if ( C4::Context->dbh->errstr ) {
-        $error.="ERROR in _koha_modify_item $query".$dbh->errstr;
+    if ( $sth->err ) {
+        $error.="ERROR in _koha_modify_item $query: ".$sth->errstr;
         warn $error;
     }
     return ($item->{'itemnumber'},$error);
@@ -2293,6 +2343,7 @@ sub _koha_delete_item {
     my $query = "INSERT INTO deleteditems SET ";
     my @bind  = ();
     foreach my $key ( keys %$data ) {
+        next if ( $key eq 'timestamp' ); # timestamp will be set by db
         $query .= "$key = ?,";
         push( @bind, $data->{$key} );
     }
@@ -2637,7 +2688,8 @@ sub PrepareItemrecordDisplay {
                 $subfield_data{mandatory}  = $tagslib->{$tag}->{$subfield}->{mandatory};
                 $subfield_data{repeatable} = $tagslib->{$tag}->{$subfield}->{repeatable};
                 $subfield_data{hidden}     = "display:none"
-                  if $tagslib->{$tag}->{$subfield}->{hidden};
+                  if ( ( $tagslib->{$tag}->{$subfield}->{hidden} > 4 )
+                    || ( $tagslib->{$tag}->{$subfield}->{hidden} < -4 ) );
                 my ( $x, $defaultvalue );
                 if ($itemrecord) {
                     ( $x, $defaultvalue ) = _find_value( $tag, $subfield, $itemrecord );
@@ -2696,7 +2748,7 @@ sub PrepareItemrecordDisplay {
                     #---- branch
                     if ( $tagslib->{$tag}->{$subfield}->{'authorised_value'} eq "branches" ) {
                         if (   ( C4::Context->preference("IndependentBranches") )
-                            && ( C4::Context->userenv->{flags} % 2 != 1 ) ) {
+                            && !C4::Context->IsSuperLibrarian() ) {
                             my $sth = $dbh->prepare( "SELECT branchcode,branchname FROM branches WHERE branchcode = ? ORDER BY branchname" );
                             $sth->execute( C4::Context->userenv->{branch} );
                             push @authorised_values, ""
@@ -2716,7 +2768,7 @@ sub PrepareItemrecordDisplay {
                             }
                         }
 
-                        $defaultvalue = C4::Context->userenv->{branch};
+                        $defaultvalue = C4::Context->userenv ? C4::Context->userenv->{branch} : undef;
                         if ( $defaultvalues and $defaultvalues->{branchcode} ) {
                             $defaultvalue = $defaultvalues->{branchcode};
                         }
@@ -2776,21 +2828,21 @@ sub PrepareItemrecordDisplay {
                             my $extended_param = plugin_parameters( $dbh, undef, $tagslib, $subfield_data{id}, undef );
                             my ( $function_name, $javascript ) = plugin_javascript( $dbh, undef, $tagslib, $subfield_data{id}, undef );
                             $subfield_data{random}     = int(rand(1000000));    # why do we need 2 different randoms?
-                            $subfield_data{marc_value} = qq[<input tabindex="1" id="$subfield_data{id}" name="field_value" class="input_marceditor" size="67" maxlength="255"
+                            $subfield_data{marc_value} = qq[<input type="text" tabindex="1" id="$subfield_data{id}" name="field_value" class="input_marceditor" size="50" maxlength="255"
                                 onfocus="Focus$function_name($subfield_data{random}, '$subfield_data{id}');"
                                  onblur=" Blur$function_name($subfield_data{random}, '$subfield_data{id}');" />
                                 <a href="#" class="buttonDot" onclick="Clic$function_name('$subfield_data{id}'); return false;" title="Tag Editor">...</a>
                                 $javascript];
                         } else {
                             warn "Plugin Failed: $plugin";
-                            $subfield_data{marc_value} = qq(<input tabindex="1" id="$subfield_data{id}" name="field_value" class="input_marceditor" size="67" maxlength="255" />); # supply default input form
+                            $subfield_data{marc_value} = qq(<input type="text" tabindex="1" id="$subfield_data{id}" name="field_value" class="input_marceditor" size="50" maxlength="255" />); # supply default input form
                         }
                 }
                 elsif ( $tag eq '' ) {       # it's an hidden field
-                    $subfield_data{marc_value} = qq(<input type="hidden" tabindex="1" id="$subfield_data{id}" name="field_value" class="input_marceditor" size="67" maxlength="255" value="$defaultvalue" />);
+                    $subfield_data{marc_value} = qq(<input type="hidden" tabindex="1" id="$subfield_data{id}" name="field_value" class="input_marceditor" size="50" maxlength="255" value="$defaultvalue" />);
                 }
                 elsif ( $tagslib->{$tag}->{$subfield}->{'hidden'} ) {   # FIXME: shouldn't input type be "hidden" ?
-                    $subfield_data{marc_value} = qq(<input type="text" tabindex="1" id="$subfield_data{id}" name="field_value" class="input_marceditor" size="67" maxlength="255" value="$defaultvalue" />);
+                    $subfield_data{marc_value} = qq(<input type="text" tabindex="1" id="$subfield_data{id}" name="field_value" class="input_marceditor" size="50" maxlength="255" value="$defaultvalue" />);
                 }
                 elsif ( length($defaultvalue) > 100
                             or (C4::Context->preference("marcflavour") eq "UNIMARC" and
@@ -2799,7 +2851,7 @@ sub PrepareItemrecordDisplay {
                                   500 <= $tag && $tag < 600                     )
                           ) {
                     # oversize field (textarea)
-                    $subfield_data{marc_value} = qq(<textarea tabindex="1" id="$subfield_data{id}" name="field_value" class="input_marceditor" size="67" maxlength="255">$defaultvalue</textarea>\n");
+                    $subfield_data{marc_value} = qq(<textarea tabindex="1" id="$subfield_data{id}" name="field_value" class="input_marceditor" size="50" maxlength="255">$defaultvalue</textarea>\n");
                 } else {
                     $subfield_data{marc_value} = "<input type=\"text\" name=\"field_value\" value=\"$defaultvalue\" size=\"50\" maxlength=\"255\" />";
                 }