| Lines 1-7
          
      
      
        Link Here | 
        
          | 1 | #!/usr/bin/perl | 1 | #!/usr/bin/perl | 
        
          | 2 |  | 2 |  | 
        
          | 3 | # Copyright 2000-2009 Biblibre S.A | 3 | # Copyright 2000-2009 Biblibre S.A | 
          
            
              | 4 | #                                         John Soros <john.soros@biblibre.com> | 4 | # John Soros <john.soros@biblibre.com> | 
        
          | 5 | # | 5 | # | 
        
          | 6 | # This file is part of Koha. | 6 | # This file is part of Koha. | 
        
          | 7 | # | 7 | # | 
  
    | Lines 18-25
          
      
      
        Link Here | 
        
          | 18 | # You should have received a copy of the GNU General Public License | 18 | # You should have received a copy of the GNU General Public License | 
        
          | 19 | # along with Koha; if not, see <http://www.gnu.org/licenses>. | 19 | # along with Koha; if not, see <http://www.gnu.org/licenses>. | 
        
          | 20 |  | 20 |  | 
          
            
              | 21 | use strict; | 21 | use Modern::Perl; | 
            
              | 22 | use warnings; |  |  | 
        
          | 23 |  | 22 |  | 
        
          | 24 | #need to open cgi and get the fh before anything else opens a new cgi context (see C4::Auth) | 23 | #need to open cgi and get the fh before anything else opens a new cgi context (see C4::Auth) | 
        
          | 25 | use CGI qw ( -utf8 ); | 24 | use CGI qw ( -utf8 ); | 
  
    | Lines 39-53
          use C4::Charset;
      
      
        Link Here | 
        
          | 39 | use Koha::DateUtils; | 38 | use Koha::DateUtils; | 
        
          | 40 | use List::MoreUtils qw( none ); | 39 | use List::MoreUtils qw( none ); | 
        
          | 41 |  | 40 |  | 
            
              | 42 |  |  |  | 
        
          | 43 | my $minlocation=$input->param('minlocation') || ''; | 41 | my $minlocation=$input->param('minlocation') || ''; | 
        
          | 44 | my $maxlocation=$input->param('maxlocation'); | 42 | my $maxlocation=$input->param('maxlocation'); | 
        
          | 45 | $maxlocation=$minlocation.'Z' unless ( $maxlocation || ! $minlocation ); | 43 | $maxlocation=$minlocation.'Z' unless ( $maxlocation || ! $minlocation ); | 
        
          | 46 | my $location=$input->param('location') || ''; | 44 | my $location=$input->param('location') || ''; | 
            
              | 47 | my $itemtype=$input->param('itemtype'); # FIXME note, template does not currently supply this |  |  | 
        
          | 48 | my $ignoreissued=$input->param('ignoreissued'); | 45 | my $ignoreissued=$input->param('ignoreissued'); | 
          
            
              | 49 | my $datelastseen = $input->param('datelastseen'); | 46 | my $datelastseen = $input->param('datelastseen'); # last inventory date | 
            
              | 50 | my $markseen = $input->param('markseen'); |  |  | 
        
          | 51 | my $branchcode = $input->param('branchcode') || ''; | 47 | my $branchcode = $input->param('branchcode') || ''; | 
        
          | 52 | my $branch     = $input->param('branch'); | 48 | my $branch     = $input->param('branch'); | 
        
          | 53 | my $op         = $input->param('op'); | 49 | my $op         = $input->param('op'); | 
  
    | Lines 115-123
          for my $statfield (qw/items.notforloan items.itemlost items.withdrawn items.dama
      
      
        Link Here | 
        
          | 115 |     } | 111 |     } | 
        
          | 116 | } | 112 | } | 
        
          | 117 |  | 113 |  | 
            
              | 118 |  |  |  | 
        
          | 119 | $template->param( statuses => $statuses ); | 114 | $template->param( statuses => $statuses ); | 
          
            
              | 120 | my $staton = {};                                #authorized values that are ticked | 115 | my $staton = {}; #authorized values that are ticked | 
        
          | 121 | for my $authvfield (@$statuses) { | 116 | for my $authvfield (@$statuses) { | 
        
          | 122 |     $staton->{$authvfield->{fieldname}} = []; | 117 |     $staton->{$authvfield->{fieldname}} = []; | 
        
          | 123 |     for my $authval (@{$authvfield->{values}}){ | 118 |     for my $authval (@{$authvfield->{values}}){ | 
  
    | Lines 141-148
          $template->param(
      
      
        Link Here | 
        
          | 141 |     compareinv2barcd         => $compareinv2barcd, | 136 |     compareinv2barcd         => $compareinv2barcd, | 
        
          | 142 | ); | 137 | ); | 
        
          | 143 |  | 138 |  | 
            
              |  |  | 139 | # Walk through uploaded barcodes, report errors, mark as seen, check in | 
            
              | 140 | my $results = {}; | 
        
          | 144 | my @scanned_items; | 141 | my @scanned_items; | 
        
          | 145 | my @errorloop; | 142 | my @errorloop; | 
            
              |  |  | 143 | my $moddatecount = 0; | 
        
          | 146 | if ( $uploadbarcodes && length($uploadbarcodes) > 0 ) { | 144 | if ( $uploadbarcodes && length($uploadbarcodes) > 0 ) { | 
        
          | 147 |     my $dbh = C4::Context->dbh; | 145 |     my $dbh = C4::Context->dbh; | 
        
          | 148 |     my $date = dt_from_string( scalar $input->param('setdate') ); | 146 |     my $date = dt_from_string( scalar $input->param('setdate') ); | 
  
    | Lines 153-160
          if ( $uploadbarcodes && length($uploadbarcodes) > 0 ) {
      
      
        Link Here | 
        
          | 153 |     $strsth="select * from items where items.barcode =? and items.withdrawn = 1"; | 151 |     $strsth="select * from items where items.barcode =? and items.withdrawn = 1"; | 
        
          | 154 |     my $qwithdrawn = $dbh->prepare($strsth); | 152 |     my $qwithdrawn = $dbh->prepare($strsth); | 
        
          | 155 |  | 153 |  | 
            
              | 156 |     my $count = 0; |  |  | 
            
              | 157 |  | 
        
          | 158 |     my @barcodes; | 154 |     my @barcodes; | 
        
          | 159 |     my @uploadedbarcodes; | 155 |     my @uploadedbarcodes; | 
        
          | 160 |  | 156 |  | 
  
    | Lines 201-303
          if ( $uploadbarcodes && length($uploadbarcodes) > 0 ) {
      
      
        Link Here | 
        
          | 201 |         } else { | 197 |         } else { | 
        
          | 202 |             my $item = GetItem( '', $barcode ); | 198 |             my $item = GetItem( '', $barcode ); | 
        
          | 203 |             if ( defined $item && $item->{'itemnumber'} ) { | 199 |             if ( defined $item && $item->{'itemnumber'} ) { | 
          
            
              | 204 |                 ModItem( { datelastseen => $date }, undef, $item->{'itemnumber'} ); | 200 |                 # Modify date last seen for scanned items, remove lost status | 
            
              | 205 |                 push @scanned_items, $item; | 201 |                 ModItem( { itemlost => 0, datelastseen => $date }, undef, $item->{'itemnumber'} ); | 
            
              | 206 |                 $count++; | 202 |                 $moddatecount++; | 
            
              |  |  | 203 |                 # update item hash accordingly | 
            
              | 204 |                 $item->{itemlost} = 0; | 
            
              | 205 |                 $item->{datelastseen} = $date; | 
        
          | 207 |                 unless ( $dont_checkin ) { | 206 |                 unless ( $dont_checkin ) { | 
        
          | 208 |                     $qonloan->execute($barcode); | 207 |                     $qonloan->execute($barcode); | 
        
          | 209 |                     if ($qonloan->rows){ | 208 |                     if ($qonloan->rows){ | 
        
          | 210 |                         my $data = $qonloan->fetchrow_hashref; | 209 |                         my $data = $qonloan->fetchrow_hashref; | 
        
          | 211 |                         my ($doreturn, $messages, $iteminformation, $borrower) =AddReturn($barcode, $data->{homebranch}); | 210 |                         my ($doreturn, $messages, $iteminformation, $borrower) =AddReturn($barcode, $data->{homebranch}); | 
          
            
              | 212 |                         if ($doreturn){ | 211 |                         if( $doreturn ) { | 
            
              | 213 |                             push @errorloop, {'barcode'=>$barcode,'ERR_ONLOAN_RET'=>1} | 212 |                             $item->{onloan} = undef; | 
            
              |  |  | 213 |                             $item->{datelastseen} = dt_from_string; | 
        
          | 214 |                         } else { | 214 |                         } else { | 
          
            
              | 215 |                             push @errorloop, {'barcode'=>$barcode,'ERR_ONLOAN_NOT_RET'=>1} | 215 |                             push @errorloop, { barcode => $barcode, ERR_ONLOAN_NOT_RET => 1 }; | 
        
          | 216 |                         } | 216 |                         } | 
        
          | 217 |                     } | 217 |                     } | 
        
          | 218 |                 } | 218 |                 } | 
            
              |  |  | 219 |                 push @scanned_items, $item; | 
        
          | 219 |             } else { | 220 |             } else { | 
          
            
              | 220 |                 push @errorloop, {'barcode'=>$barcode,'ERR_BARCODE'=>1}; | 221 |                 push @errorloop, { barcode => $barcode, ERR_BARCODE => 1 }; | 
        
          | 221 |             } | 222 |             } | 
        
          | 222 |         } | 223 |         } | 
            
              | 223 |  |  |  | 
        
          | 224 |     } | 224 |     } | 
          
            
              | 225 |  | 225 |     $template->param( date => $date ); | 
            
              | 226 |     $template->param( date => $date, Number => $count ); |  |  | 
        
          | 227 |     $template->param( errorloop => \@errorloop ) if (@errorloop); | 226 |     $template->param( errorloop => \@errorloop ) if (@errorloop); | 
        
          | 228 | } | 227 | } | 
        
          | 229 |  | 228 |  | 
          
            
              | 230 | # now build the result list: inventoried items if requested, and mis-placed items -always- | 229 | # Build inventorylist: used as result list when you do not pass barcodes | 
            
              | 231 | my $inventorylist; | 230 | # This list is also used when you want to compare with barcodes | 
            
              | 232 | my $wrongplacelist; | 231 | my ( $inventorylist, $rightplacelist ); | 
            
              | 233 | my @items_with_problems; | 232 | if ( $op && ( !$uploadbarcodes || $compareinv2barcd )) { | 
            
              | 234 | if ( $markseen or $op ) { | 233 |     ( $inventorylist ) = GetItemsForInventory({ | 
            
              | 235 |     # retrieve all items in this range. |  |  | 
            
              | 236 |     my $totalrecords; | 
            
              | 237 |  | 
            
              | 238 |     # We use datelastseen only when comparing the results to the barcode file. | 
            
              | 239 |     my $paramdatelastseen = ($compareinv2barcd) ? $datelastseen : ''; | 
            
              | 240 |     ($inventorylist, $totalrecords) = GetItemsForInventory( { | 
        
          | 241 |       minlocation  => $minlocation, | 234 |       minlocation  => $minlocation, | 
        
          | 242 |       maxlocation  => $maxlocation, | 235 |       maxlocation  => $maxlocation, | 
        
          | 243 |       location     => $location, | 236 |       location     => $location, | 
            
              | 244 |       itemtype     => $itemtype, |  |  | 
        
          | 245 |       ignoreissued => $ignoreissued, | 237 |       ignoreissued => $ignoreissued, | 
          
            
              | 246 |       datelastseen => $paramdatelastseen, | 238 |       datelastseen => $datelastseen, | 
        
          | 247 |       branchcode   => $branchcode, | 239 |       branchcode   => $branchcode, | 
        
          | 248 |       branch       => $branch, | 240 |       branch       => $branch, | 
        
          | 249 |       offset       => 0, | 241 |       offset       => 0, | 
            
              | 250 |       size         => undef, |  |  | 
        
          | 251 |       statushash   => $staton, | 242 |       statushash   => $staton, | 
        
          | 252 |       interface    => 'staff', | 243 |       interface    => 'staff', | 
          
            
              | 253 |     } ); | 244 |     }); | 
            
              | 254 |  | 245 | } | 
            
              | 255 |     # For the items that may be marked as "wrong place", we only check the location (callnumbers, location and branch) | 246 | # Build rightplacelist used to check if a scanned item is in the right place. | 
            
              | 256 |     ($wrongplacelist, $totalrecords) = GetItemsForInventory( { | 247 | if( @scanned_items ) { | 
            
              |  |  | 248 |     ( $rightplacelist ) = GetItemsForInventory({ | 
        
          | 257 |       minlocation  => $minlocation, | 249 |       minlocation  => $minlocation, | 
        
          | 258 |       maxlocation  => $maxlocation, | 250 |       maxlocation  => $maxlocation, | 
        
          | 259 |       location     => $location, | 251 |       location     => $location, | 
            
              | 260 |       itemtype     => undef, |  |  | 
        
          | 261 |       ignoreissued => undef, | 252 |       ignoreissued => undef, | 
        
          | 262 |       datelastseen => undef, | 253 |       datelastseen => undef, | 
        
          | 263 |       branchcode   => $branchcode, | 254 |       branchcode   => $branchcode, | 
        
          | 264 |       branch       => $branch, | 255 |       branch       => $branch, | 
        
          | 265 |       offset       => 0, | 256 |       offset       => 0, | 
            
              | 266 |       size         => undef, |  |  | 
        
          | 267 |       statushash   => undef, | 257 |       statushash   => undef, | 
        
          | 268 |       interface    => 'staff', | 258 |       interface    => 'staff', | 
          
            
              | 269 |     } ); | 259 |     }); | 
            
              | 270 |  | 260 |     # Convert the structure to a hash on barcode | 
            
              |  |  | 261 |     $rightplacelist = { | 
            
              | 262 |         map { $_->{barcode} ? ( $_->{barcode}, $_ ) : (); } @$rightplacelist | 
            
              | 263 |     }; | 
        
          | 271 | } | 264 | } | 
        
          | 272 |  | 265 |  | 
          
            
              | 273 | # If "compare barcodes list to results" has been checked, we want to alert for missing items | 266 | # Report scanned items that are on the wrong place, or have a wrong notforloan | 
            
              | 274 | if ( $compareinv2barcd ) { | 267 | # status, or are still checked out. | 
            
              | 275 |     # set "missing" flags for all items with a datelastseen (dls) before the chosen datelastseen (cdls) |  |  | 
            
              | 276 |     my $dls = output_pref( { dt => dt_from_string( $datelastseen ), | 
            
              | 277 |                              dateformat => 'iso' } ); | 
            
              | 278 |     foreach my $item ( @$inventorylist ) { | 
            
              | 279 |         my $cdls = output_pref( { dt => dt_from_string( $item->{datelastseen} ), | 
            
              | 280 |                                   dateformat => 'iso' } ); | 
            
              | 281 |         if ( $cdls lt $dls ) { | 
            
              | 282 |             $item->{problem} = 'missingitem'; | 
            
              | 283 |             # We have to push a copy of the item, not the reference | 
            
              | 284 |             push @items_with_problems, { %$item }; | 
            
              | 285 |         } | 
            
              | 286 |     } | 
            
              | 287 | } | 
            
              | 288 |  | 
            
              | 289 |  | 
            
              | 290 |  | 
            
              | 291 | # insert "wrongplace" to all scanned items that are not supposed to be in this range | 
            
              | 292 | # note this list is always displayed, whatever the librarian has chosen for comparison | 
            
              | 293 | my $moddatecount = 0; | 
        
          | 294 | foreach my $item ( @scanned_items ) { | 268 | foreach my $item ( @scanned_items ) { | 
            
              |  |  | 269 |     $item->{notforloancode} = $item->{notforloan}; # save for later use | 
        
          | 295 |  | 270 |  | 
          
            
              | 296 |   # Saving notforloan code before it's replaced by it's authorised value for later comparison | 271 |     # Populating with authorised values | 
            
              | 297 |   $item->{notforloancode} = $item->{notforloan}; | 272 |     foreach my $field ( keys %$item ) { | 
            
              | 298 |  |  |  | 
            
              | 299 |   # Populating with authorised values | 
            
              | 300 |   foreach my $field ( keys %$item ) { | 
        
          | 301 |         # If the koha field is mapped to a marc field | 273 |         # If the koha field is mapped to a marc field | 
        
          | 302 |         my $fc = $item->{'frameworkcode'} || ''; | 274 |         my $fc = $item->{'frameworkcode'} || ''; | 
        
          | 303 |         my ($f, $sf) = GetMarcFromKohaField("items.$field", $fc); | 275 |         my ($f, $sf) = GetMarcFromKohaField("items.$field", $fc); | 
  
    | Lines 310-363
          foreach my $item ( @scanned_items ) {
      
      
        Link Here | 
        
          | 310 |         } | 282 |         } | 
        
          | 311 |     } | 283 |     } | 
        
          | 312 |  | 284 |  | 
            
              | 313 |     next if $item->{onloan}; # skip checked out items |  |  | 
            
              | 314 |  | 
        
          | 315 |     # If we have scanned items with a non-matching notforloan value | 285 |     # If we have scanned items with a non-matching notforloan value | 
          
            
              | 316 |     if (none { $item->{'notforloancode'} eq $_ } @notforloans) { | 286 |     if( none { $item->{'notforloancode'} eq $_ } @notforloans ) { | 
            
              | 317 |         $item->{problem} = 'changestatus'; | 287 |         $item->{problems}->{changestatus} = 1; | 
            
              | 318 |         push @items_with_problems, { %$item }; | 288 |         additemtoresults( $item, $results ); | 
            
              | 319 |     } |  |  | 
            
              | 320 |     if (none { $item->{barcode} eq $_->{barcode} && !$_->{'onloan'} } @$wrongplacelist) { | 
            
              | 321 |         $item->{problem} = 'wrongplace'; | 
            
              | 322 |         push @items_with_problems, { %$item }; | 
        
          | 323 |     } | 289 |     } | 
        
          | 324 |  | 290 |  | 
          
            
              | 325 |     # Modify date last seen for scanned items | 291 |     # Report an item that is checked out (unusual!) or wrongly placed | 
            
              | 326 |     ModDateLastSeen($item->{'itemnumber'}); | 292 |     if( $item->{onloan} ) { | 
            
              | 327 |     $moddatecount++; | 293 |         $item->{problems}->{checkedout} = 1; | 
            
              |  |  | 294 |         additemtoresults( $item, $results ); | 
            
              | 295 |         next; # do not modify item | 
            
              | 296 |     } elsif( !exists $rightplacelist->{ $item->{barcode} } ) { | 
            
              | 297 |         $item->{problems}->{wrongplace} = 1; | 
            
              | 298 |         additemtoresults( $item, $results ); | 
            
              | 299 |     } | 
        
          | 328 | } | 300 | } | 
        
          | 329 |  | 301 |  | 
            
              |  |  | 302 | # Compare barcodes with inventory list, report no_barcode and not_scanned. | 
            
              | 303 | # not_scanned can be interpreted as missing | 
        
          | 330 | if ( $compareinv2barcd ) { | 304 | if ( $compareinv2barcd ) { | 
        
          | 331 |     my @scanned_barcodes = map {$_->{barcode}} @scanned_items; | 305 |     my @scanned_barcodes = map {$_->{barcode}} @scanned_items; | 
          
            
              | 332 |     for my $should_be_scanned ( @$inventorylist ) { | 306 |     for my $item ( @$inventorylist ) { | 
            
              | 333 |         my $barcode = $should_be_scanned->{barcode}; | 307 |         my $barcode = $item->{barcode}; | 
            
              | 334 |         unless ( grep /^$barcode$/, @scanned_barcodes ) { | 308 |         if( !$barcode ) { | 
            
              | 335 |             $should_be_scanned->{problem} = 'not_scanned'; | 309 |             $item->{problems}->{no_barcode} = 1; | 
            
              | 336 |             push @items_with_problems, { %$should_be_scanned }; | 310 |         } elsif ( grep /^$barcode$/, @scanned_barcodes ) { | 
            
              |  |  | 311 |             next; | 
            
              | 312 |         } else { | 
            
              | 313 |             $item->{problems}->{not_scanned} = 1; | 
        
          | 337 |         } | 314 |         } | 
            
              |  |  | 315 |         additemtoresults( $item, $results ); | 
        
          | 338 |     } | 316 |     } | 
        
          | 339 | } | 317 | } | 
        
          | 340 |  | 318 |  | 
          
            
              | 341 | for my $item ( @items_with_problems ) { | 319 | # Construct final results, add biblio information | 
            
              |  |  | 320 | my $loop = $uploadbarcodes | 
            
              | 321 |     ? [ map { $results->{$_} } keys %$results ] | 
            
              | 322 |     : $inventorylist // []; | 
            
              | 323 | for my $item ( @$loop ) { | 
        
          | 342 |     my $biblio = C4::Biblio::GetBiblioData($item->{biblionumber}); | 324 |     my $biblio = C4::Biblio::GetBiblioData($item->{biblionumber}); | 
        
          | 343 |     $item->{title} = $biblio->{title}; | 325 |     $item->{title} = $biblio->{title}; | 
        
          | 344 |     $item->{author} = $biblio->{author}; | 326 |     $item->{author} = $biblio->{author}; | 
        
          | 345 | } | 327 | } | 
        
          | 346 |  | 328 |  | 
            
              | 347 | # If a barcode file is given, we want to show problems, else all items |  |  | 
            
              | 348 | my @results; | 
            
              | 349 | @results = $uploadbarcodes | 
            
              | 350 |             ? @items_with_problems | 
            
              | 351 |             : $op | 
            
              | 352 |                 ? @$inventorylist | 
            
              | 353 |                 : (); | 
            
              | 354 |  | 
        
          | 355 | $template->param( | 329 | $template->param( | 
        
          | 356 |     moddatecount => $moddatecount, | 330 |     moddatecount => $moddatecount, | 
          
            
              | 357 |     loop       => \@results, | 331 |     loop         => $loop, | 
            
              | 358 |     op         => $op | 332 |     op           => $op, | 
        
          | 359 | ); | 333 | ); | 
        
          | 360 |  | 334 |  | 
            
              |  |  | 335 | # Export to csv | 
        
          | 361 | if (defined $input->param('CSVexport') && $input->param('CSVexport') eq 'on'){ | 336 | if (defined $input->param('CSVexport') && $input->param('CSVexport') eq 'on'){ | 
        
          | 362 |     eval {use Text::CSV}; | 337 |     eval {use Text::CSV}; | 
        
          | 363 |     my $csv = Text::CSV->new or | 338 |     my $csv = Text::CSV->new or | 
  
    | Lines 392-413
          if (defined $input->param('CSVexport') && $input->param('CSVexport') eq 'on'){
      
      
        Link Here | 
        
          | 392 |     print $csv->string, "\n"; | 367 |     print $csv->string, "\n"; | 
        
          | 393 |  | 368 |  | 
        
          | 394 |     my @keys = qw / title author barcode itemnumber homebranch location itemcallnumber notforloan lost damaged withdrawn stocknumber /; | 369 |     my @keys = qw / title author barcode itemnumber homebranch location itemcallnumber notforloan lost damaged withdrawn stocknumber /; | 
          
            
              | 395 |     for my $item ( @results ) { | 370 |     for my $item ( @$loop ) { | 
        
          | 396 |         my @line; | 371 |         my @line; | 
        
          | 397 |         for my $key (@keys) { | 372 |         for my $key (@keys) { | 
        
          | 398 |             push @line, $item->{$key}; | 373 |             push @line, $item->{$key}; | 
        
          | 399 |         } | 374 |         } | 
          
            
              | 400 |         if ( defined $item->{problem} ) { | 375 |         my $errstr = ''; | 
            
              | 401 |             if ( $item->{problem} eq 'wrongplace' ) { | 376 |         foreach my $key ( keys %{$item->{problems}} ) { | 
            
              | 402 |                 push @line, "wrong place"; | 377 |             if( $key eq 'wrongplace' ) { | 
            
              | 403 |             } elsif ( $item->{problem} eq 'missingitem' ) { | 378 |                 $errstr .= "wrong place,"; | 
            
              | 404 |                 push @line, "missing item"; | 379 |             } elsif( $key eq 'changestatus' ) { | 
            
              | 405 |             } elsif ( $item->{problem} eq 'changestatus' ) { | 380 |                 $errstr .= "unknown notforloan status,"; | 
            
              | 406 |                 push @line, "change item status"; | 381 |             } elsif( $key eq 'not_scanned' ) { | 
            
              | 407 |             } elsif ($item->{problem} eq 'not_scanned' ) { | 382 |                 $errstr .= "missing,"; | 
            
              | 408 |                 push @line, "item not scanned"; | 383 |             } elsif( $key eq 'no_barcode' ) { | 
            
              |  |  | 384 |                 $errstr .= "no barcode,"; | 
            
              | 385 |             } elsif( $key eq 'checkedout' ) { | 
            
              | 386 |                 $errstr .= "checked out,"; | 
        
          | 409 |             } | 387 |             } | 
        
          | 410 |         } | 388 |         } | 
            
              |  |  | 389 |         $errstr =~ s/,$//; | 
            
              | 390 |         push @line, $errstr; | 
        
          | 411 |         $csv->combine(@line); | 391 |         $csv->combine(@line); | 
        
          | 412 |         print $csv->string, "\n"; | 392 |         print $csv->string, "\n"; | 
        
          | 413 |     } | 393 |     } | 
  
    | Lines 425-427
          if (defined $input->param('CSVexport') && $input->param('CSVexport') eq 'on'){
      
      
        Link Here | 
        
          | 425 | } | 405 | } | 
        
          | 426 |  | 406 |  | 
        
          | 427 | output_html_with_http_headers $input, $cookie, $template->output; | 407 | output_html_with_http_headers $input, $cookie, $template->output; | 
          
            
              | 428 | -  | 408 |  | 
            
              |  |  | 409 | sub additemtoresults { | 
            
              | 410 |     my ( $item, $results ) = @_; | 
            
              | 411 |     my $itemno = $item->{itemnumber}; | 
            
              | 412 |     # since the script appends to $item, we can just overwrite the hash entry | 
            
              | 413 |     $results->{$itemno} = $item; | 
            
              | 414 | } |