View | Details | Raw Unified | Return to bug 6557
Collapse All | Expand All

(-)a/misc/cronjobs/crontab.example (+3 lines)
Lines 67-72 KOHA_CRON_PATH = /usr/share/koha/bin/cronjobs Link Here
67
# Cancel expired holds
67
# Cancel expired holds
68
0 1 * * *  $KOHA_CRON_PATH/holds/cancel_expired_holds.pl >/dev/null 2>&1
68
0 1 * * *  $KOHA_CRON_PATH/holds/cancel_expired_holds.pl >/dev/null 2>&1
69
69
70
# Update popularity counts for biblio records
71
0 2 * * *  $KOHA_CRON_PATH/update_totalissues.pl --commit=1000 --use-stats --incremental --interval=1d >/dev/null 2>&1
72
70
# ZEBRA INDEX UPDATES with -z option, incremental index updates throughout the day
73
# ZEBRA INDEX UPDATES with -z option, incremental index updates throughout the day
71
# for both authorities and bibs
74
# for both authorities and bibs
72
*/10 * * * *  $KOHA_CRON_PATH/../migration_tools/rebuild_zebra.pl -b -a -z >/dev/null
75
*/10 * * * *  $KOHA_CRON_PATH/../migration_tools/rebuild_zebra.pl -b -a -z >/dev/null
(-)a/misc/cronjobs/update_totalissues.pl (-1 / +272 lines)
Line 0 Link Here
0
- 
1
#!/usr/bin/perl
2
3
# Copyright 2012 C & P Bibliography Services
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it under the
8
# terms of the GNU General Public License as published by the Free Software
9
# Foundation; either version 2 of the License, or (at your option) any later
10
# version.
11
#
12
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
13
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License along
17
# with Koha; if not, write to the Free Software Foundation, Inc.,
18
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
20
use strict;
21
use warnings;
22
23
BEGIN {
24
25
    # find Koha's Perl modules
26
    # test carefully before changing this
27
    use FindBin;
28
    eval { require "$FindBin::Bin/../kohalib.pl" };
29
}
30
31
use Getopt::Long;
32
use Pod::Usage;
33
use C4::Context;
34
use C4::Biblio;
35
use DateTime;
36
use DateTime::Format::MySQL;
37
use Time::HiRes qw/time/;
38
use POSIX qw/strftime ceil/;
39
40
sub usage {
41
    pod2usage( -verbose => 2 );
42
    exit;
43
}
44
45
$| = 1;
46
47
# command-line parameters
48
my $verbose   = 0;
49
my $test_only = 0;
50
my $want_help = 0;
51
my $since;
52
my $interval;
53
my $usestats    = 0;
54
my $useitems    = 0;
55
my $incremental = 0;
56
my $commit      = 100;
57
my $unit;
58
59
my $result = GetOptions(
60
    'v|verbose'    => \$verbose,
61
    't|test'       => \$test_only,
62
    's|since=s'    => \$since,
63
    'i|interval=s' => \$interval,
64
    'use-stats'    => \$usestats,
65
    'use-items'    => \$useitems,
66
    'incremental'  => \$incremental,
67
    'c|commit=i'   => \$commit,
68
    'h|help'       => \$want_help
69
);
70
71
binmode( STDOUT, ":utf8" );
72
73
if ( defined $since && defined $interval ) {
74
    print "The --since and --interval options are mutually exclusive.\n\n";
75
    $want_help = 1;
76
}
77
78
if ( $usestats && $incremental ) {
79
    print
80
      "The --use-items and --incremental options are mutually exclusive.\n\n";
81
    $want_help = 1;
82
}
83
84
unless ( $usestats || $useitems ) {
85
    print "You must specify either --use-stats and/or --use-items.\n\n";
86
    $want_help = 1;
87
}
88
89
if ( not $result or $want_help ) {
90
    usage();
91
}
92
93
my $dbh = C4::Context->dbh;
94
$dbh->{AutoCommit} = 0;
95
96
my $num_bibs_processed = 0;
97
98
my $starttime = time();
99
100
process_items() if $useitems;
101
process_stats() if $usestats;
102
103
report();
104
105
exit 0;
106
107
sub process_items {
108
    my $query =
109
"SELECT items.biblionumber, SUM(items.issues) FROM items GROUP BY items.biblionumber;";
110
    process_query($query);
111
}
112
113
sub process_stats {
114
    if ($interval) {
115
        my $dt = DateTime->now;
116
117
        my %units = (
118
            h => 'hours',
119
            d => 'days',
120
            w => 'weeks',
121
            m => 'months',
122
            y => 'years'
123
        );
124
125
        $interval =~ m/([0-9]*)([hdwmy]?)$/;
126
        $unit = $2 || 'd';
127
        $since = DateTime::Format::MySQL->format_datetime(
128
            $dt->subtract( $units{$unit} => $1 ) );
129
    }
130
    my $limit = '';
131
    $limit = " AND statistics.datetime >= ?" if ( $interval || $since );
132
133
    my $query =
134
"SELECT biblio.biblionumber, COUNT(statistics.itemnumber) FROM biblio LEFT JOIN items ON (biblio.biblionumber=items.itemnumber) LEFT JOIN statistics ON (items.itemnumber=statistics.itemnumber) WHERE statistics.type = 'issue' $limit GROUP BY biblio.biblionumber;";
135
    process_query($query);
136
137
    unless ($incremental) {
138
        $query =
139
"SELECT biblio.biblionumber, 0 FROM biblio LEFT JOIN items ON (biblio.biblionumber=items.itemnumber) LEFT JOIN statistics ON (items.itemnumber=statistics.itemnumber) WHERE statistics.itemnumber IS NULL GROUP BY biblio.biblionumber;";
140
        process_query($query);
141
142
        $query =
143
"SELECT biblio.biblionumber, 0 FROM biblio LEFT JOIN items ON (biblio.biblionumber=items.itemnumber) WHERE items.itemnumber IS NULL GROUP BY biblio.biblionumber;";
144
        process_query($query);
145
    }
146
147
    $dbh->commit();
148
}
149
150
sub process_query {
151
    my $query = shift;
152
    my $sth   = $dbh->prepare($query);
153
154
    if ($since) {
155
        $sth->execute($since);
156
    }
157
    else {
158
        $sth->execute();
159
    }
160
161
    while ( my ( $biblionumber, $totalissues ) = $sth->fetchrow_array() ) {
162
        $num_bibs_processed++;
163
        print "Processing bib $biblionumber ($totalissues issues)\n"
164
          if $verbose;
165
        if ( not $test_only ) {
166
            if ( $incremental && $totalissues > 0 ) {
167
                UpdateTotalIssues( $biblionumber, $totalissues );
168
            }
169
            else {
170
                UpdateTotalIssues( $biblionumber, 0, $totalissues );
171
            }
172
        }
173
        if ( not $test_only and ( $num_bibs_processed % $commit ) == 0 ) {
174
            print_progress_and_commit($num_bibs_processed);
175
        }
176
    }
177
178
    $dbh->commit();
179
}
180
181
sub report {
182
    my $endtime = time();
183
    my $totaltime = ceil( ( $endtime - $starttime ) * 1000 );
184
    $starttime = strftime( '%D %T', localtime($starttime) );
185
    $endtime   = strftime( '%D %T', localtime($endtime) );
186
187
    my $summary = <<_SUMMARY_;
188
189
Update total issues count script report
190
=======================================================
191
Run started at:                         $starttime
192
Run ended at:                           $endtime
193
Total run time:                         $totaltime ms
194
Number of bibs modified:                $num_bibs_processed
195
_SUMMARY_
196
    $summary .= "\n****  Ran in test mode only  ****\n" if $test_only;
197
    print $summary;
198
}
199
200
sub print_progress_and_commit {
201
    my $recs = shift;
202
    $dbh->commit();
203
    print "... processed $recs records\n";
204
}
205
206
=head1 NAME
207
208
update_totalissues.pl
209
210
=head1 SYNOPSIS
211
212
  update_totalissues.pl --use-stats
213
  update_totalissues.pl --use-items
214
  update_totalissues.pl --commit=1000
215
  update_totalissues.pl --since='2012-01-01'
216
  update_totalissues.pl --interval=30d
217
218
=head1 DESCRIPTION
219
220
This batch job populates bibliographic records' total issues count based
221
on historical issue statistics.
222
223
=over 8
224
225
=item B<--help>
226
227
Prints this help
228
229
=item B<-v|--verbose>
230
231
Provide verbose log information (list every bib modified).
232
233
=item B<--use-stats>
234
235
Use the data in the statistics table for populating total issues.
236
237
=item B<--use-items>
238
239
Use items.issues data for populating total issues. Note that issues
240
data from the items table does not respect the --since or --interval
241
options, by definition. Also note that if both --use-stats and
242
--use-items are specified, the count of biblios processed will be
243
misleading.
244
245
=item B<-s|--since=DATE>
246
247
Only process issues recorded in the statistics table since DATE.
248
249
=item B<-i|--interval=S>
250
251
Only process issues recorded in the statistics table in the last N
252
units of time. The interval should consist of a number with a one-letter
253
unit suffix. The valid suffixes are h (hours), d (days), w (weeks),
254
m (months), and y (years). The default unit is days.
255
256
=item B<--incremental>
257
258
Add the number of issues found in the statistics table to the existing
259
total issues count. Intended so that this script can be used as a cron
260
job to update popularity information during low-usage periods.
261
262
=item B<--commit=N>
263
264
Commit the results to the database after every N records are processed.
265
266
=item B<--test>
267
268
Only test the popularity population script.
269
270
=back
271
272
=cut

Return to bug 6557