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 / +291 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
        $totalissues = 0 unless $totalissues;
167
        if ( not $test_only ) {
168
            if ( $incremental && $totalissues > 0 ) {
169
                UpdateTotalIssues( $biblionumber, $totalissues );
170
            }
171
            else {
172
                UpdateTotalIssues( $biblionumber, 0, $totalissues );
173
            }
174
        }
175
        if ( not $test_only and ( $num_bibs_processed % $commit ) == 0 ) {
176
            print_progress_and_commit($num_bibs_processed);
177
        }
178
    }
179
180
    $dbh->commit();
181
}
182
183
sub report {
184
    my $endtime = time();
185
    my $totaltime = ceil( ( $endtime - $starttime ) * 1000 );
186
    $starttime = strftime( '%D %T', localtime($starttime) );
187
    $endtime   = strftime( '%D %T', localtime($endtime) );
188
189
    my $summary = <<_SUMMARY_;
190
191
Update total issues count script report
192
=======================================================
193
Run started at:                         $starttime
194
Run ended at:                           $endtime
195
Total run time:                         $totaltime ms
196
Number of bibs modified:                $num_bibs_processed
197
_SUMMARY_
198
    $summary .= "\n****  Ran in test mode only  ****\n" if $test_only;
199
    print $summary;
200
}
201
202
sub print_progress_and_commit {
203
    my $recs = shift;
204
    $dbh->commit();
205
    print "... processed $recs records\n";
206
}
207
208
=head1 NAME
209
210
update_totalissues.pl
211
212
=head1 SYNOPSIS
213
214
  update_totalissues.pl --use-stats
215
  update_totalissues.pl --use-items
216
  update_totalissues.pl --commit=1000
217
  update_totalissues.pl --since='2012-01-01'
218
  update_totalissues.pl --interval=30d
219
220
=head1 DESCRIPTION
221
222
This batch job populates bibliographic records' total issues count based
223
on historical issue statistics.
224
225
=over 8
226
227
=item B<--help>
228
229
Prints this help
230
231
=item B<-v|--verbose>
232
233
Provide verbose log information (list every bib modified).
234
235
=item B<--use-stats>
236
237
Use the data in the statistics table for populating total issues.
238
239
=item B<--use-items>
240
241
Use items.issues data for populating total issues. Note that issues
242
data from the items table does not respect the --since or --interval
243
options, by definition. Also note that if both --use-stats and
244
--use-items are specified, the count of biblios processed will be
245
misleading.
246
247
=item B<-s|--since=DATE>
248
249
Only process issues recorded in the statistics table since DATE.
250
251
=item B<-i|--interval=S>
252
253
Only process issues recorded in the statistics table in the last N
254
units of time. The interval should consist of a number with a one-letter
255
unit suffix. The valid suffixes are h (hours), d (days), w (weeks),
256
m (months), and y (years). The default unit is days.
257
258
=item B<--incremental>
259
260
Add the number of issues found in the statistics table to the existing
261
total issues count. Intended so that this script can be used as a cron
262
job to update popularity information during low-usage periods.
263
264
=item B<--commit=N>
265
266
Commit the results to the database after every N records are processed.
267
268
=item B<--test>
269
270
Only test the popularity population script.
271
272
=back
273
274
=head1 WARNING
275
276
If the time on your database server does not match the time on your Koha
277
server you will need to take that into account, and probably use the
278
--since argument instead of the --interval argument for incremental 
279
updating.
280
281
=head1 CREDITS
282
283
This patch to Koha was sponsored by the Arcadia Public Library and the
284
Arcadia Public Library Foundation in honor of Jackie Faust-Moreno, late
285
director of the Arcadia Public Library.
286
287
=head1 AUTHOR
288
289
Jared Camins-Esakov <jcamins AT cpbibliography DOT com>
290
291
=cut

Return to bug 6557