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 / +273 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 ( $useitems && $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.biblionumber) LEFT JOIN statistics ON (items.itemnumber=statistics.itemnumber) WHERE statistics.type = 'issue' $limit GROUP BY biblio.biblionumber;";
135
    process_query($query, $limit);
136
137
    unless ($incremental) {
138
        $query =
139
"SELECT biblio.biblionumber, 0 FROM biblio LEFT JOIN items ON (biblio.biblionumber=items.biblionumber) 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.biblionumber) 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 $uselimit = shift;
153
    my $sth   = $dbh->prepare($query);
154
155
    if ($since && $uselimit) {
156
        $sth->execute($since);
157
    }
158
    else {
159
        $sth->execute();
160
    }
161
162
    while ( my ( $biblionumber, $totalissues ) = $sth->fetchrow_array() ) {
163
        $num_bibs_processed++;
164
        print "Processing bib $biblionumber ($totalissues issues)\n"
165
          if $verbose;
166
        if ( not $test_only ) {
167
            if ( $incremental && $totalissues > 0 ) {
168
                UpdateTotalIssues( $biblionumber, $totalissues );
169
            }
170
            else {
171
                UpdateTotalIssues( $biblionumber, 0, $totalissues );
172
            }
173
        }
174
        if ( not $test_only and ( $num_bibs_processed % $commit ) == 0 ) {
175
            print_progress_and_commit($num_bibs_processed);
176
        }
177
    }
178
179
    $dbh->commit();
180
}
181
182
sub report {
183
    my $endtime = time();
184
    my $totaltime = ceil( ( $endtime - $starttime ) * 1000 );
185
    $starttime = strftime( '%D %T', localtime($starttime) );
186
    $endtime   = strftime( '%D %T', localtime($endtime) );
187
188
    my $summary = <<_SUMMARY_;
189
190
Update total issues count script report
191
=======================================================
192
Run started at:                         $starttime
193
Run ended at:                           $endtime
194
Total run time:                         $totaltime ms
195
Number of bibs modified:                $num_bibs_processed
196
_SUMMARY_
197
    $summary .= "\n****  Ran in test mode only  ****\n" if $test_only;
198
    print $summary;
199
}
200
201
sub print_progress_and_commit {
202
    my $recs = shift;
203
    $dbh->commit();
204
    print "... processed $recs records\n";
205
}
206
207
=head1 NAME
208
209
update_totalissues.pl
210
211
=head1 SYNOPSIS
212
213
  update_totalissues.pl --use-stats
214
  update_totalissues.pl --use-items
215
  update_totalissues.pl --commit=1000
216
  update_totalissues.pl --since='2012-01-01'
217
  update_totalissues.pl --interval=30d
218
219
=head1 DESCRIPTION
220
221
This batch job populates bibliographic records' total issues count based
222
on historical issue statistics.
223
224
=over 8
225
226
=item B<--help>
227
228
Prints this help
229
230
=item B<-v|--verbose>
231
232
Provide verbose log information (list every bib modified).
233
234
=item B<--use-stats>
235
236
Use the data in the statistics table for populating total issues.
237
238
=item B<--use-items>
239
240
Use items.issues data for populating total issues. Note that issues
241
data from the items table does not respect the --since or --interval
242
options, by definition. Also note that if both --use-stats and
243
--use-items are specified, the count of biblios processed will be
244
misleading.
245
246
=item B<-s|--since=DATE>
247
248
Only process issues recorded in the statistics table since DATE.
249
250
=item B<-i|--interval=S>
251
252
Only process issues recorded in the statistics table in the last N
253
units of time. The interval should consist of a number with a one-letter
254
unit suffix. The valid suffixes are h (hours), d (days), w (weeks),
255
m (months), and y (years). The default unit is days.
256
257
=item B<--incremental>
258
259
Add the number of issues found in the statistics table to the existing
260
total issues count. Intended so that this script can be used as a cron
261
job to update popularity information during low-usage periods.
262
263
=item B<--commit=N>
264
265
Commit the results to the database after every N records are processed.
266
267
=item B<--test>
268
269
Only test the popularity population script.
270
271
=back
272
273
=cut

Return to bug 6557