Bug 30952: Bring back bullet points for lists
[srvgit] / tools / inventory.pl
index eff4fe2..ace4e7c 100755 (executable)
@@ -24,22 +24,25 @@ use Modern::Perl;
 use CGI qw ( -utf8 );
 my $input = CGI->new;
 my $uploadbarcodes = $input->param('uploadbarcodes');
+my $barcodelist = $input->param('barcodelist');
 
-use C4::Auth;
+use C4::Auth qw( get_template_and_user );
 use C4::Context;
-use C4::Output;
-use C4::Biblio;
-use C4::Items;
-use C4::Koha;
-use C4::Circulation;
-use C4::Reports::Guided;    #_get_column_defs
-use C4::Charset;
+use C4::Output qw( output_html_with_http_headers );
+use C4::Items qw( GetItemsForInventory );
+use C4::Koha qw( GetAuthorisedValues );
+use C4::Circulation qw( barcodedecode AddReturn );
+use C4::Reports::Guided qw( );
+use C4::Charset qw( NormalizeString );
 
 use Koha::Biblios;
-use Koha::DateUtils;
+use Koha::DateUtils qw( dt_from_string );
+use Koha::Database::Columns;
 use Koha::AuthorisedValues;
 use Koha::BiblioFrameworks;
 use Koha::ClassSources;
+use Koha::Items;
+
 use List::MoreUtils qw( none );
 
 my $minlocation=$input->param('minlocation') || '';
@@ -56,14 +59,13 @@ my $op         = $input->param('op');
 my $compareinv2barcd = $input->param('compareinv2barcd');
 my $dont_checkin = $input->param('dont_checkin');
 my $out_of_order = $input->param('out_of_order');
+my $ccode = $input->param('ccode');
 
 my ( $template, $borrowernumber, $cookie ) = get_template_and_user(
     {   template_name   => "tools/inventory.tt",
         query           => $input,
         type            => "intranet",
-        authnotrequired => 0,
         flagsrequired   => { tools => 'inventory' },
-        debug           => 1,
     }
 );
 
@@ -73,6 +75,9 @@ my $authorisedvalue_categories = '';
 my $frameworks = Koha::BiblioFrameworks->search({}, { order_by => ['frameworktext'] })->unblessed;
 unshift @$frameworks, { frameworkcode => '' };
 
+my @collections = ();
+my @collection_codes = ();
+
 for my $fwk ( @$frameworks ){
   my $fwkcode = $fwk->{frameworkcode};
   my $mss = Koha::MarcSubfieldStructures->search({ frameworkcode => $fwkcode, kohafield => 'items.location', authorised_value => [ -and => {'!=' => undef }, {'!=' => ''}] });
@@ -118,9 +123,20 @@ for my $authvfield (@$statuses) {
     }
 }
 
-my @class_sources = Koha::ClassSources->search({ used => 1 });
+# if there's a list of not for loans types selected use it rather than
+# the full set.
+@notforloans = @{$staton->{'items.notforloan'}} if defined $staton->{'items.notforloan'} and scalar @{$staton->{'items.notforloan'}} > 0;
+
+my @class_sources = Koha::ClassSources->search({ used => 1 })->as_list;
 my $pref_class = C4::Context->preference("DefaultClassificationSource");
 
+my @itemtypes = Koha::ItemTypes->search->as_list;
+my @selected_itemtypes;
+foreach my $itemtype ( @itemtypes ) {
+    if ( defined $input->param('itemtype-' . $itemtype->itemtype) ) {
+        push @selected_itemtypes, "'" . $itemtype->itemtype . "'";
+    }
+}
 
 $template->param(
     authorised_values        => \@authorised_value_list,
@@ -133,10 +149,12 @@ $template->param(
     branch                   => $branch,
     datelastseen             => $datelastseen,
     compareinv2barcd         => $compareinv2barcd,
-    uploadedbarcodesflag     => $uploadbarcodes ? 1 : 0,
+    uploadedbarcodesflag     => ($uploadbarcodes || $barcodelist) ? 1 : 0,
     ignore_waiting_holds     => $ignore_waiting_holds,
     class_sources            => \@class_sources,
-    pref_class               => $pref_class
+    pref_class               => $pref_class,
+    itemtypes                => \@itemtypes,
+    ccode                    => $ccode,
 );
 
 # Walk through uploaded barcodes, report errors, mark as seen, check in
@@ -144,10 +162,10 @@ my $results = {};
 my @scanned_items;
 my @errorloop;
 my $moddatecount = 0;
-if ( $uploadbarcodes && length($uploadbarcodes) > 0 ) {
+if ( ($uploadbarcodes && length($uploadbarcodes) > 0) || ($barcodelist && length($barcodelist) > 0) ) {
     my $dbh = C4::Context->dbh;
-    my $date = dt_from_string( scalar $input->param('setdate') );
-    $date = output_pref ( { dt => $date, dateformat => 'iso' } );
+    my $date = $input->param('setdate');
+    my $date_dt = dt_from_string($date);
 
     my $strsth  = "select * from issues, items where items.itemnumber=issues.itemnumber and items.barcode =?";
     my $qonloan = $dbh->prepare($strsth);
@@ -163,12 +181,21 @@ if ( $uploadbarcodes && length($uploadbarcodes) > 0 ) {
     my $err_length=0;
     my $err_data=0;
     my $lines_read=0;
-    binmode($uploadbarcodes, ":encoding(UTF-8)");
-    while (my $barcode=<$uploadbarcodes>) {
-        push @uploadedbarcodes, grep { /\S/ } split( /[\n\r,;|-]/, $barcode );
+    if ($uploadbarcodes && length($uploadbarcodes) > 0) {
+        binmode($uploadbarcodes, ":encoding(UTF-8)");
+        while (my $barcode=<$uploadbarcodes>) {
+            my $split_chars = C4::Context->preference('BarcodeSeparators');
+            push @uploadedbarcodes, grep { /\S/ } split( /[$split_chars]/, $barcode );
+        }
+    } else {
+        push @uploadedbarcodes, split(/\s\n/, scalar $input->param('barcodelist') );
+        $uploadbarcodes = $barcodelist;
     }
     for my $barcode (@uploadedbarcodes) {
         next unless $barcode;
+
+        $barcode = barcodedecode($barcode);
+
         ++$lines_read;
         if (length($barcode)>$barcode_size) {
             $err_length += 1;
@@ -195,28 +222,26 @@ if ( $uploadbarcodes && length($uploadbarcodes) > 0 ) {
         if ( $qwithdrawn->execute($barcode) && $qwithdrawn->rows ) {
             push @errorloop, { 'barcode' => $barcode, 'ERR_WTHDRAWN' => 1 };
         } else {
-            my $item = GetItem( '', $barcode );
-            if ( defined $item && $item->{'itemnumber'} ) {
+            my $item = Koha::Items->find({barcode => $barcode});
+            if ( $item ) {
                 # Modify date last seen for scanned items, remove lost status
-                ModItem( { itemlost => 0, datelastseen => $date }, undef, $item->{'itemnumber'} );
+                $item->set({ itemlost => 0, datelastseen => $date_dt })->store;
+                my $item_unblessed = $item->unblessed;
                 $moddatecount++;
-                # update item hash accordingly
-                $item->{itemlost} = 0;
-                $item->{datelastseen} = $date;
                 unless ( $dont_checkin ) {
                     $qonloan->execute($barcode);
                     if ($qonloan->rows){
                         my $data = $qonloan->fetchrow_hashref;
                         my ($doreturn, $messages, $iteminformation, $borrower) =AddReturn($barcode, $data->{homebranch});
                         if( $doreturn ) {
-                            $item->{onloan} = undef;
-                            $item->{datelastseen} = dt_from_string;
+                            $item_unblessed->{onloan} = undef;
+                            $item_unblessed->{datelastseen} = dt_from_string;
                         } else {
                             push @errorloop, { barcode => $barcode, ERR_ONLOAN_NOT_RET => 1 };
                         }
                     }
                 }
-                push @scanned_items, $item;
+                push @scanned_items, $item_unblessed;
             } else {
                 push @errorloop, { barcode => $barcode, ERR_BARCODE => 1 };
             }
@@ -241,11 +266,14 @@ if ( $op && ( !$uploadbarcodes || $compareinv2barcd )) {
       branch       => $branch,
       offset       => 0,
       statushash   => $staton,
+      ccode        => $ccode,
       ignore_waiting_holds => $ignore_waiting_holds,
+      itemtypes    => \@selected_itemtypes,
     });
 }
 # Build rightplacelist used to check if a scanned item is in the right place.
 if( @scanned_items ) {
+    # For the items that may be marked as "wrong place", we only check the location (callnumbers, location, ccode and branch)
     ( $rightplacelist ) = GetItemsForInventory({
       minlocation  => $minlocation,
       maxlocation  => $maxlocation,
@@ -258,11 +286,14 @@ if( @scanned_items ) {
       offset       => 0,
       statushash   => undef,
       ignore_waiting_holds => $ignore_waiting_holds,
+      itemtypes    => \@selected_itemtypes,
+      ccode        => $ccode,
     });
     # Convert the structure to a hash on barcode
     $rightplacelist = {
         map { $_->{barcode} ? ( $_->{barcode}, $_ ) : (); } @$rightplacelist
     };
+
 }
 
 # Report scanned items that are on the wrong place, or have a wrong notforloan
@@ -326,7 +357,7 @@ if ( $compareinv2barcd ) {
         my $barcode = $item->{barcode};
         if( !$barcode ) {
             $item->{problems}->{no_barcode} = 1;
-        } elsif ( grep /^$barcode$/, @scanned_barcodes ) {
+        } elsif ( grep { $_ eq $barcode } @scanned_barcodes ) {
             next;
         } else {
             $item->{problems}->{not_scanned} = 1;
@@ -353,7 +384,7 @@ $template->param(
 
 # Export to csv
 if (defined $input->param('CSVexport') && $input->param('CSVexport') eq 'on'){
-    eval {use Text::CSV};
+    eval {use Text::CSV ();};
     my $csv = Text::CSV->new or
             die Text::CSV->error_diag ();
     binmode STDOUT, ":encoding(UTF-8)";
@@ -362,30 +393,24 @@ if (defined $input->param('CSVexport') && $input->param('CSVexport') eq 'on'){
         -attachment => 'inventory.csv',
     );
 
-    my $columns_def_hashref = C4::Reports::Guided::_get_column_defs($input);
-    foreach my $key ( keys %$columns_def_hashref ) {
-        my $initkey = $key;
-        $key =~ s/[^\.]*\.//;
-        $columns_def_hashref->{$initkey}=NormalizeString($columns_def_hashref->{$initkey} // '');
-        $columns_def_hashref->{$key} = $columns_def_hashref->{$initkey};
-    }
-
+    my $columns = Koha::Database::Columns->columns;
     my @translated_keys;
     for my $key (qw / biblioitems.title    biblio.author
                       items.barcode        items.itemnumber
-                      items.homebranch     items.location
+                      items.homebranch     items.location   items.ccode
                       items.itemcallnumber items.notforloan
                       items.itemlost       items.damaged
                       items.withdrawn      items.stocknumber
                       / ) {
-       push @translated_keys, $columns_def_hashref->{$key};
+        my ( $table, $column ) = split '\.', $key;
+        push @translated_keys, NormalizeString($columns->{$table}->{$column} // '');
     }
     push @translated_keys, 'problem' if $uploadbarcodes;
 
     $csv->combine(@translated_keys);
     print $csv->string, "\n";
 
-    my @keys = qw/ title author barcode itemnumber homebranch location itemcallnumber notforloan itemlost damaged withdrawn stocknumber /;
+    my @keys = qw/ title author barcode itemnumber homebranch location ccode itemcallnumber notforloan itemlost damaged withdrawn stocknumber /;
     for my $item ( @$loop ) {
         my @line;
         for my $key (@keys) {