| Lines 38-101
          use C4::Items;
      
      
        Link Here | 
        
          | 38 | use C4::Circulation qw/LostItem/; | 38 | use C4::Circulation qw/LostItem/; | 
        
          | 39 | use Getopt::Long; | 39 | use Getopt::Long; | 
        
          | 40 | use C4::Log; | 40 | use C4::Log; | 
            
              |  |  | 41 | use Pod::Usage; | 
        
          | 41 |  | 42 |  | 
        
          | 42 | my  $lost;  #  key=lost value,  value=num days. | 43 | my  $lost;  #  key=lost value,  value=num days. | 
        
          | 43 | my ($charge, $verbose, $confirm, $quiet); | 44 | my ($charge, $verbose, $confirm, $quiet); | 
        
          | 44 | my $endrange = 366; | 45 | my $endrange = 366; | 
        
          | 45 | my $mark_returned = 0; | 46 | my $mark_returned = 0; | 
            
              |  |  | 47 | my $borrower_category = []; | 
            
              | 48 | my $skip_borrower_category = []; | 
            
              | 49 | my $help=0; | 
            
              | 50 | my $man=0; | 
        
          | 46 |  | 51 |  | 
          
            
              | 47 | GetOptions(  | 52 | GetOptions( | 
            
              | 48 |     'lost=s%'       => \$lost, | 53 |     'lost=s%'         => \$lost, | 
            
              | 49 |     'c|charge=s'    => \$charge, | 54 |     'c|charge=s'      => \$charge, | 
            
              | 50 |     'confirm'       => \$confirm, | 55 |     'confirm'         => \$confirm, | 
            
              | 51 |     'verbose'       => \$verbose, | 56 |     'verbose'         => \$verbose, | 
            
              | 52 |     'quiet'         => \$quiet, | 57 |     'quiet'           => \$quiet, | 
            
              | 53 |     'maxdays=s'     => \$endrange, | 58 |     'maxdays=s'       => \$endrange, | 
            
              | 54 |     'mark-returned' => \$mark_returned, | 59 |     'mark-returned'   => \$mark_returned, | 
            
              |  |  | 60 |     'help'            => \$help, | 
            
              | 61 |     'man|manual'      => \$man, | 
            
              | 62 |     'category=s'      => $borrower_category, | 
            
              | 63 |     'skip-category=s' => $skip_borrower_category | 
        
          | 55 | ); | 64 | ); | 
        
          | 56 |  | 65 |  | 
          
            
              | 57 | my $usage = << 'ENDUSAGE'; | 66 | if ( $man ) { | 
            
              | 58 | longoverdue.pl : This cron script set lost values on overdue items and optionally sets charges the patron's account | 67 |     pod2usage( -verbose => 2 ); | 
            
              | 59 | for the item's replacement price.  It is designed to be run as a nightly job.  The command line options that globally | 68 |     exit; | 
            
              | 60 | define this behavior for this script  will likely be moved into Koha's core circulation / issuing rules code in a  | 69 | } | 
            
              | 61 | near-term release, so this script is not intended to have a long lifetime.   | 70 |  | 
            
              |  |  | 71 | if ( $help ) { | 
            
              | 72 |     pod2usage(1); | 
            
              | 73 |     exit; | 
            
              | 74 | } | 
            
              | 75 |  | 
            
              | 76 | =head1 SYNOPSIS | 
            
              | 77 |  | 
            
              | 78 |    longoverdue.pl [ --help | -h | --man ] | 
            
              | 79 |    longoverdue.pl --lost | -l DAYS=LOST_CODE [ --charge | -c CHARGE_CODE ] [ --verbose | -v ] [ --quiet ] | 
            
              | 80 |                   [ --maxdays MAX_DAYS ] [ --mark-returned ] [ --category BORROWER_CATEGOERY ] ... | 
            
              | 81 |                   [ --skip-category BORROWER_CATEGOERY ] ... [ --commit ] | 
            
              | 82 |  | 
            
              | 83 |  | 
            
              | 84 | WARNING:  Flippant use of this script could set all or most of the items in your catalog to Lost and charge your | 
            
              | 85 |           patrons for them! | 
            
              | 86 |  | 
            
              | 87 | WARNING:  This script is known to be faulty.  It is NOT recommended to use multiple --lost options. | 
            
              | 88 |           See http://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=2883 | 
            
              | 89 |  | 
            
              | 90 | =cut | 
            
              | 91 |  | 
            
              | 92 | =head1 OPTIONS | 
        
          | 62 |  | 93 |  | 
        
          | 63 | This script takes the following parameters : | 94 | This script takes the following parameters : | 
        
          | 64 |  | 95 |  | 
          
            
              | 65 |     --lost | -l         This option takes the form of n=lv, | 96 | =over 8 | 
            
              | 66 |                         where n is num days overdue, and lv is the lost value.  See warning below. | 97 |  | 
            
              |  |  | 98 | =item B<--lost | -l> | 
            
              | 99 |  | 
            
              | 100 | This option takes the form of n=lv, where n is num days overdue, and lv is the lost value.  See warning above. | 
            
              | 101 |  | 
            
              | 102 | =item B<--charge | -c> | 
            
              | 103 |  | 
            
              | 104 | This specifies what lost value triggers Koha to charge the account for the lost item.  Replacement costs are not charged if this is not specified. | 
            
              | 105 |  | 
            
              | 106 | =item B<--verbose | -v> | 
            
              | 107 |  | 
            
              | 108 | verbose. | 
            
              | 109 |  | 
            
              | 110 | =item B<--confirm> | 
            
              | 111 |  | 
            
              | 112 | confirm.  without this option, the script will report the number of affected items and return without modifying any records. | 
            
              | 113 |  | 
            
              | 114 | =item B<--quiet> | 
            
              | 115 |  | 
            
              | 116 | suppress summary output. | 
            
              | 117 |  | 
            
              | 118 | =item B<--maxdays> | 
            
              | 119 |  | 
            
              | 120 | Specifies the end of the range of overdue days to deal with (defaults to 366).  This value is universal to all lost num days overdue passed. | 
            
              | 121 |  | 
            
              | 122 | =item B<--mark-returned> | 
            
              | 123 |  | 
            
              | 124 | When an item is marked lost, remove it from the borrowers issued items. | 
            
              | 125 |  | 
            
              | 126 | =item B<--category> | 
            
              | 127 |  | 
            
              | 128 | Act on the listed borrower category code (borrowers.categorycode). Exclude all others. This may be specified multiple times to include multiple categories. | 
            
              | 129 |  | 
            
              | 130 | =item B<--skip-category> | 
        
          | 67 |  | 131 |  | 
          
            
              | 68 |     --charge | -c       This specifies what lost value triggers Koha to charge the account for the | 132 | Act on all available borrower category codes, except those listed.  This may be specified multiple times, to exclude multiple categories. | 
            
              | 69 |                         lost item.  Replacement costs are not charged if this is not specified. |  |  | 
        
          | 70 |  | 133 |  | 
          
            
              | 71 |     --verbose | v       verbose. | 134 | =item B<--help | -h> | 
        
          | 72 |  | 135 |  | 
          
            
              | 73 |     --confirm           confirm.  without this option, the script will report the number of affected items and | 136 | Display short help message an exit. | 
            
              | 74 |                         return without modifying any records. |  |  | 
        
          | 75 |  | 137 |  | 
          
            
              | 76 |     --quiet             suppress summary output. | 138 | =item B<--man | --manual > | 
        
          | 77 |  | 139 |  | 
          
            
              | 78 |     --maxdays           Specifies the end of the range of overdue days to deal with (defaults to 366).  This | 140 | Display entire manual and exit. | 
            
              | 79 |                         value is universal to all lost num days overdue passed. |  |  | 
        
          | 80 |  | 141 |  | 
          
            
              | 81 |     --mark-returned     When an item is marked lost, remove it from the borrowers issued items. | 142 | =back | 
            
              |  |  | 143 |  | 
            
              | 144 | All 'category' options will be applied before any 'skip-category' options, meaning that the only categories available to skip | 
            
              | 145 | are those which have already been specified on the command line. | 
            
              | 146 |  | 
            
              | 147 | =cut | 
            
              | 148 |  | 
            
              | 149 | =head1 Description | 
            
              | 150 |  | 
            
              | 151 | This cron script set lost values on overdue items and optionally sets charges the patron's account | 
            
              | 152 | for the item's replacement price.  It is designed to be run as a nightly job.  The command line options that globally | 
            
              | 153 | define this behavior for this script  will likely be moved into Koha's core circulation / issuing rules code in a | 
            
              | 154 | near-term release, so this script is not intended to have a long lifetime. | 
            
              | 155 |  | 
            
              | 156 |  | 
            
              | 157 | =cut | 
            
              | 158 |  | 
            
              | 159 | =head1 Examples | 
        
          | 82 |  | 160 |  | 
            
              | 83 |   examples : |  |  | 
        
          | 84 |   $PERL5LIB/misc/cronjobs/longoverdue.pl --lost 30=1 | 161 |   $PERL5LIB/misc/cronjobs/longoverdue.pl --lost 30=1 | 
        
          | 85 |     Would set LOST=1 after 30 days (up to one year), but not charge the account. | 162 |     Would set LOST=1 after 30 days (up to one year), but not charge the account. | 
        
          | 86 |     This would be suitable for the Koha default LOST authorized value of 1 -> 'Lost'. | 163 |     This would be suitable for the Koha default LOST authorized value of 1 -> 'Lost'. | 
        
          | 87 |  | 164 |  | 
        
          | 88 |   $PERL5LIB/misc/cronjobs/longoverdue.pl --lost 60=2 --charge 2 | 165 |   $PERL5LIB/misc/cronjobs/longoverdue.pl --lost 60=2 --charge 2 | 
        
          | 89 |     Would set LOST=2 after 60 days (up to one year), and charge the account when setting LOST=2. | 166 |     Would set LOST=2 after 60 days (up to one year), and charge the account when setting LOST=2. | 
          
            
              | 90 |     This would be suitable for the Koha default LOST authorized value of 2 -> 'Long Overdue'  | 167 |     This would be suitable for the Koha default LOST authorized value of 2 -> 'Long Overdue' | 
            
              | 91 |  |  |  | 
            
              | 92 | WARNING:  Flippant use of this script could set all or most of the items in your catalog to Lost and charge your | 
            
              | 93 | patrons for them! | 
        
          | 94 |  | 168 |  | 
          
            
              | 95 | WARNING:  This script is known to be faulty.  It is NOT recommended to use multiple --lost options. | 169 | =cut | 
            
              | 96 |           See http://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=2883 |  |  | 
            
              | 97 |  | 
            
              | 98 | ENDUSAGE | 
        
          | 99 |  | 170 |  | 
        
          | 100 | # FIXME: We need three pieces of data to operate: | 171 | # FIXME: We need three pieces of data to operate: | 
        
          | 101 | #         ~ lower bound (number of days), | 172 | #         ~ lower bound (number of days), | 
  
    | Lines 105-113
          ENDUSAGE
      
      
        Link Here | 
        
          | 105 | # FIXME: do checks on --lost ranges to make sure they are exclusive. | 176 | # FIXME: do checks on --lost ranges to make sure they are exclusive. | 
        
          | 106 | # FIXME: do checks on --lost ranges to make sure the authorized values exist. | 177 | # FIXME: do checks on --lost ranges to make sure the authorized values exist. | 
        
          | 107 | # FIXME: do checks on --lost ranges to make sure don't go past endrange. | 178 | # FIXME: do checks on --lost ranges to make sure don't go past endrange. | 
          
            
              | 108 | # FIXME: convert to using pod2usage | 179 | # | 
            
              | 109 | # FIXME: allow --help or -h |  |  | 
            
              | 110 | #  | 
        
          | 111 | if ( ! defined($lost) ) { | 180 | if ( ! defined($lost) ) { | 
        
          | 112 |     my $longoverdue_value = C4::Context->preference('DefaultLongOverdueLostValue'); | 181 |     my $longoverdue_value = C4::Context->preference('DefaultLongOverdueLostValue'); | 
        
          | 113 |     my $longoverdue_days = C4::Context->preference('DefaultLongOverdueDays'); | 182 |     my $longoverdue_days = C4::Context->preference('DefaultLongOverdueDays'); | 
  
    | Lines 115-121
          if ( ! defined($lost) ) {
      
      
        Link Here | 
        
          | 115 |         $lost->{$longoverdue_days} = $longoverdue_value; | 184 |         $lost->{$longoverdue_days} = $longoverdue_value; | 
        
          | 116 |     } | 185 |     } | 
        
          | 117 |     else { | 186 |     else { | 
          
            
              | 118 |         print $usage; | 187 |         pod2usage(1); | 
        
          | 119 |         die "ERROR: No --lost (-l) option defined"; | 188 |         die "ERROR: No --lost (-l) option defined"; | 
        
          | 120 |     } | 189 |     } | 
        
          | 121 | } | 190 | } | 
  
    | Lines 154-163
          sub longoverdue_sth {
      
      
        Link Here | 
        
          | 154 |     return C4::Context->dbh->prepare($query); | 223 |     return C4::Context->dbh->prepare($query); | 
        
          | 155 | } | 224 | } | 
        
          | 156 |  | 225 |  | 
            
              |  |  | 226 | # The following two functions can and should replaced by a call to | 
            
              | 227 | # Koha::Database. | 
            
              | 228 | sub borrower_categories_sth { | 
            
              | 229 |     my $query = "select distinct categorycode from categories"; | 
            
              | 230 |     return C4::Context->dbh->prepare($query); | 
            
              | 231 | } | 
            
              | 232 |  | 
            
              | 233 | sub defined_borrower_categories { | 
            
              | 234 |     my $sth = borrower_categories_sth(); | 
            
              | 235 |     my @categories = (); | 
            
              | 236 |     $sth->execute(); | 
            
              | 237 |     CATEGORY: while ( my $row = $sth->fetchrow_hashref ) { | 
            
              | 238 |         push @categories, uc( $row->{categorycode} ); | 
            
              | 239 |     } | 
            
              | 240 |     return @categories; | 
            
              | 241 | } | 
            
              | 242 |  | 
            
              | 243 | # returns a hash of borrower category codes to test for long-overdue-ness. | 
            
              | 244 | # The key is the borrower category, upper case. The value is 1. This | 
            
              | 245 | # will make a fast look-up of valid borrower category codes. | 
            
              | 246 | sub get_borrower_categories { | 
            
              | 247 |     my ( $borrower_category, $skip_borrower_category ) = ( @_ ); | 
            
              | 248 |  | 
            
              | 249 |     return () unless ( scalar @$borrower_category || scalar @$skip_borrower_category ); | 
            
              | 250 |  | 
            
              | 251 |     my @categories = defined_borrower_categories(); | 
            
              | 252 |     if( @$borrower_category ) { | 
            
              | 253 |         my %borcat  = map { ( uc($_) => 1 ) } @$borrower_category; | 
            
              | 254 |         @categories = grep { $borcat{$_} } @categories; | 
            
              | 255 |     } | 
            
              | 256 |     if( @$skip_borrower_category ) { | 
            
              | 257 |         my %skip_borcat  = map { ( uc($_) => 1 ) } @$skip_borrower_category; | 
            
              | 258 |         @categories = grep { ! $skip_borcat{$_} } @categories; | 
            
              | 259 |     } | 
            
              | 260 |     return map { $_ => 1 } @categories; | 
            
              | 261 | } | 
            
              | 262 |  | 
            
              | 263 | # TODO: category handling should be more user friendly: | 
            
              | 264 | #       * Warn if a category specified using --category or | 
            
              | 265 | #         --skip-category is not in the categories table | 
            
              | 266 | #       * Add --list-categories argument so that you don't | 
            
              | 267 | #         need to bring up the staff client or koha-mysql to | 
            
              | 268 | #         find the valid borrower categories. | 
            
              | 269 |  | 
            
              | 270 | my %category_to_process = get_borrower_categories( $borrower_category, $skip_borrower_category ); | 
            
              | 271 | my $filter_borrower_categories = ( scalar @$borrower_category || scalar @$skip_borrower_category ); | 
            
              | 272 |  | 
        
          | 157 | #FIXME - Should add a 'system' user and get suitable userenv for it for logging, etc. | 273 | #FIXME - Should add a 'system' user and get suitable userenv for it for logging, etc. | 
        
          | 158 |  | 274 |  | 
        
          | 159 | my $count; | 275 | my $count; | 
          
            
              | 160 | # my @ranges = map {  | 276 | # my @ranges = map { | 
        
          | 161 | my @report; | 277 | my @report; | 
        
          | 162 | my $total = 0; | 278 | my $total = 0; | 
        
          | 163 | my $i = 0; | 279 | my $i = 0; | 
  
    | Lines 172-183
          foreach my $startrange (sort keys %$lost) {
      
      
        Link Here | 
        
          | 172 |         my ($date1) = bounds($startrange); | 288 |         my ($date1) = bounds($startrange); | 
        
          | 173 |         my ($date2) = bounds(  $endrange); | 289 |         my ($date2) = bounds(  $endrange); | 
        
          | 174 |         # print "\nRange ", ++$i, "\nDue $startrange - $endrange days ago ($date2 to $date1), lost => $lostvalue\n" if($verbose); | 290 |         # print "\nRange ", ++$i, "\nDue $startrange - $endrange days ago ($date2 to $date1), lost => $lostvalue\n" if($verbose); | 
          
            
              | 175 |         $verbose and  | 291 |         $verbose and | 
        
          | 176 |             printf "\nRange %s\nDue %3s - %3s days ago (%s to %s), lost => %s\n", ++$i, | 292 |             printf "\nRange %s\nDue %3s - %3s days ago (%s to %s), lost => %s\n", ++$i, | 
        
          | 177 |             $startrange, $endrange, $date2, $date1, $lostvalue; | 293 |             $startrange, $endrange, $date2, $date1, $lostvalue; | 
        
          | 178 |         $sth_items->execute($startrange, $endrange, $lostvalue); | 294 |         $sth_items->execute($startrange, $endrange, $lostvalue); | 
        
          | 179 |         $count=0; | 295 |         $count=0; | 
          
            
              | 180 |         while (my $row=$sth_items->fetchrow_hashref) { | 296 |         ITEM: while (my $row=$sth_items->fetchrow_hashref) { | 
            
              |  |  | 297 |             if( $filter_borrower_categories ) { | 
            
              | 298 |                 my $category = uc Koha::Database->new()->schema->resultset('Borrower')->find( $row->{borrowernumber} )->get_column('categorycode'); | 
            
              | 299 |                 next ITEM unless ( $category_to_process{ $category } ); | 
            
              | 300 |             } | 
        
          | 181 |             printf ("Due %s: item %5s from borrower %5s to lost: %s\n", $row->{date_due}, $row->{itemnumber}, $row->{borrowernumber}, $lostvalue) if($verbose); | 301 |             printf ("Due %s: item %5s from borrower %5s to lost: %s\n", $row->{date_due}, $row->{itemnumber}, $row->{borrowernumber}, $lostvalue) if($verbose); | 
        
          | 182 |             if($confirm) { | 302 |             if($confirm) { | 
        
          | 183 |                 ModItem({ itemlost => $lostvalue }, $row->{'biblionumber'}, $row->{'itemnumber'}); | 303 |                 ModItem({ itemlost => $lostvalue }, $row->{'biblionumber'}, $row->{'itemnumber'}); | 
            
              | 184 | -  |  |  |