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

(-)a/C4/Circulation.pm (-2 / +22 lines)
Lines 2536-2552 sub GetBiblioIssues { Link Here
2536
=head2 GetUpcomingDueIssues
2536
=head2 GetUpcomingDueIssues
2537
2537
2538
  my $upcoming_dues = GetUpcomingDueIssues( { days_in_advance => 4 } );
2538
  my $upcoming_dues = GetUpcomingDueIssues( { days_in_advance => 4 } );
2539
  my $upcoming_dues = GetUpcomingDueIssues( { date_in_history => '2014-09-15' } );
2539
2540
2541
@PARAM date_in_history must be a ISO 8601 compatible YYYY-MM-DD date string.
2542
       This function will behave just like if it was ran on the given date in history.
2540
=cut
2543
=cut
2541
2544
2542
sub GetUpcomingDueIssues {
2545
sub GetUpcomingDueIssues {
2543
    my $params = shift;
2546
    my $params = shift;
2544
2547
2545
    $params->{'days_in_advance'} = 7 unless exists $params->{'days_in_advance'};
2548
    $params->{'days_in_advance'} = 7 unless exists $params->{'days_in_advance'};
2549
    #Define $params->{'date_to_calculate'},
2550
    if (exists $params->{'date_in_history'}) { #Validate YYYY-MM-DD and get it!
2551
        if ($params->{'date_in_history'} =~ /^(\d\d\d\d-\d\d-\d\d)[ T]?/) {
2552
            $params->{'date_to_calculate'} = $1;
2553
        }
2554
        else {
2555
            warn "Parameter 'date_in_history' ".$params->{'date_in_history'}." is not a valid ISO 8601 Date or compatible! It must match /^YYYY-MM-DD/\nreturning undef!";
2556
            return;
2557
        }
2558
    }
2559
    else { #Default to NOW()
2560
        #Getting the ISO 8601 Date in the most efficient way for the computer :)
2561
        my @t = localtime;   $t[5] += 1900;   $t[4]++;
2562
        $params->{'date_to_calculate'} = sprintf "%04d-%02d-%02d", @t[5,4,3];
2563
    }
2564
2546
    my $dbh = C4::Context->dbh;
2565
    my $dbh = C4::Context->dbh;
2547
2566
2548
    my $statement = <<END_SQL;
2567
    my $statement = <<END_SQL;
2549
SELECT issues.*, items.itype as itemtype, items.homebranch, TO_DAYS( date_due )-TO_DAYS( NOW() ) as days_until_due, branches.branchemail
2568
SELECT issues.*, items.itype as itemtype, items.homebranch, TO_DAYS( date_due )-TO_DAYS( ? ) as days_until_due, branches.branchemail
2550
FROM issues 
2569
FROM issues 
2551
LEFT JOIN items USING (itemnumber)
2570
LEFT JOIN items USING (itemnumber)
2552
LEFT OUTER JOIN branches USING (branchcode)
2571
LEFT OUTER JOIN branches USING (branchcode)
Lines 2554-2560 WHERE returndate is NULL Link Here
2554
HAVING days_until_due >= 0 AND days_until_due <= ?
2573
HAVING days_until_due >= 0 AND days_until_due <= ?
2555
END_SQL
2574
END_SQL
2556
2575
2557
    my @bind_parameters = ( $params->{'days_in_advance'} );
2576
    my @bind_parameters = ( $params->{'date_to_calculate'},
2577
                            $params->{'days_in_advance'});
2558
    
2578
    
2559
    my $sth = $dbh->prepare( $statement );
2579
    my $sth = $dbh->prepare( $statement );
2560
    $sth->execute( @bind_parameters );
2580
    $sth->execute( @bind_parameters );
(-)a/misc/cronjobs/advance_notices.pl (-8 / +47 lines)
Lines 105-110 defaults to due date,title,author,barcode Link Here
105
Other possible values come from fields in the biblios, items and
105
Other possible values come from fields in the biblios, items and
106
issues tables.
106
issues tables.
107
107
108
=item B<--date_in_history>
109
110
YYYY-MM-DD of the date from which to generate advance notices.
111
Used to fix failed advance_notices.pl-cronjob runs, or for debugging purposes.
112
So if today is 2014-09-15 and you want to run advance_notices.pl for two days
113
ago, you can run "advance_notices.pl -c --date_in_history 2014-09-13 -n"
114
to generate those notifications.
115
Be aware not to send advance notices after users have received overdue
116
notifications!
117
118
To fix a crashed advance_notices.pl-run two days ago, run the following command:
119
  advance_notices.pl -c --date_in_history 2014-09-13 \
120
  --exclude_days_until_due 2,0 -n
121
Be aware that you have already sent the advance notices for users requesting the
122
notice 2 days in advance, and also the overdue notification is sent.
123
Remove -n -flag if you get the desired result.
124
125
=item B<--exclude_days_until_due>
126
127
An array of integers, each a duration in days in advance to NOT send advance notices.
128
You can skip processing of some advance notices which have days_until_due of the
129
given values. See --date_in_history for a useful usage scenario.
130
131
ex. --exclude_days_until_due 0,2,3
132
108
=back
133
=back
109
134
110
=head1 DESCRIPTION
135
=head1 DESCRIPTION
Lines 170-175 my $mindays = 0; # -m: Maximu Link Here
170
my $maxdays     = 30;                                               # -e: the End of the time period
195
my $maxdays     = 30;                                               # -e: the End of the time period
171
my $verbose     = 0;                                                # -v: verbose
196
my $verbose     = 0;                                                # -v: verbose
172
my $itemscontent = join(',',qw( date_due title author barcode ));
197
my $itemscontent = join(',',qw( date_due title author barcode ));
198
my $exclude_days_until_due;
199
200
#Defaulting $date_in_history to NOW()
201
#Getting the ISO 8601 Date in the most efficient way for the computer :)
202
my @t = localtime;   $t[5] += 1900;   $t[4]++;
203
my $date_in_history = sprintf "%04d-%02d-%02d", @t[5,4,3];
204
undef @t; #Don't pollute package namespace!
173
205
174
my $help    = 0;
206
my $help    = 0;
175
my $man     = 0;
207
my $man     = 0;
Lines 182-187 GetOptions( Link Here
182
            'm:i'            => \$maxdays,
214
            'm:i'            => \$maxdays,
183
            'v'              => \$verbose,
215
            'v'              => \$verbose,
184
            'itemscontent=s' => \$itemscontent,
216
            'itemscontent=s' => \$itemscontent,
217
            'date_in_history=s' => \$date_in_history,
218
            'exclude_days_until_due=s' => \$exclude_days_until_due,
185
       )or pod2usage(2);
219
       )or pod2usage(2);
186
pod2usage(1) if $help;
220
pod2usage(1) if $help;
187
pod2usage( -verbose => 2 ) if $man;;
221
pod2usage( -verbose => 2 ) if $man;;
Lines 205-211 unless ($confirm) { Link Here
205
my @item_content_fields = split(/,/,$itemscontent);
239
my @item_content_fields = split(/,/,$itemscontent);
206
240
207
warn 'getting upcoming due issues' if $verbose;
241
warn 'getting upcoming due issues' if $verbose;
208
my $upcoming_dues = C4::Circulation::GetUpcomingDueIssues( { days_in_advance => $maxdays } );
242
my $upcoming_dues = C4::Circulation::GetUpcomingDueIssues( { days_in_advance => $maxdays, date_in_history => $date_in_history } );
209
warn 'found ' . scalar( @$upcoming_dues ) . ' issues' if $verbose;
243
warn 'found ' . scalar( @$upcoming_dues ) . ' issues' if $verbose;
210
244
211
# hash of borrowernumber to number of items upcoming
245
# hash of borrowernumber to number of items upcoming
Lines 221-227 SELECT biblio.*, items.*, issues.* Link Here
221
    AND biblio.biblionumber=items.biblionumber
255
    AND biblio.biblionumber=items.biblionumber
222
    AND issues.borrowernumber = ?
256
    AND issues.borrowernumber = ?
223
    AND issues.itemnumber = ?
257
    AND issues.itemnumber = ?
224
    AND (TO_DAYS(date_due)-TO_DAYS(NOW()) = ?)
258
    AND (TO_DAYS(date_due)-TO_DAYS(?) = ?)
225
END_SQL
259
END_SQL
226
260
227
my $admin_adress = C4::Context->preference('KohaAdminEmailAddress');
261
my $admin_adress = C4::Context->preference('KohaAdminEmailAddress');
Lines 232-237 UPCOMINGITEM: foreach my $upcoming ( @$upcoming_dues ) { Link Here
232
    warn 'examining ' . $upcoming->{'itemnumber'} . ' upcoming due items' if $verbose;
266
    warn 'examining ' . $upcoming->{'itemnumber'} . ' upcoming due items' if $verbose;
233
    # warn( Data::Dumper->Dump( [ $upcoming ], [ 'overdue' ] ) );
267
    # warn( Data::Dumper->Dump( [ $upcoming ], [ 'overdue' ] ) );
234
268
269
    #Skip some days for --exclude_days_until_due
270
    my $days_until_due = $upcoming->{'days_until_due'};
271
    if (defined $exclude_days_until_due && $exclude_days_until_due =~ /(^|,)$days_until_due(,|$)/) {
272
        next UPCOMINGITEM;
273
    }
274
235
    my $from_address = $upcoming->{branchemail} || $admin_adress;
275
    my $from_address = $upcoming->{branchemail} || $admin_adress;
236
276
237
    my $borrower_preferences;
277
    my $borrower_preferences;
Lines 250-256 UPCOMINGITEM: foreach my $upcoming ( @$upcoming_dues ) { Link Here
250
        } else {
290
        } else {
251
            my $biblio = C4::Biblio::GetBiblioFromItemNumber( $upcoming->{'itemnumber'} );
291
            my $biblio = C4::Biblio::GetBiblioFromItemNumber( $upcoming->{'itemnumber'} );
252
            my $letter_type = 'DUE';
292
            my $letter_type = 'DUE';
253
            $sth->execute($upcoming->{'borrowernumber'},$upcoming->{'itemnumber'},'0');
293
            $sth->execute($upcoming->{'borrowernumber'},$upcoming->{'itemnumber'},$date_in_history,'0');
254
            my $titles = "";
294
            my $titles = "";
255
            while ( my $item_info = $sth->fetchrow_hashref()) {
295
            while ( my $item_info = $sth->fetchrow_hashref()) {
256
              my @item_info = map { $_ =~ /^date|date$/ ? format_date($item_info->{$_}) : $item_info->{$_} || '' } @item_content_fields;
296
              my @item_info = map { $_ =~ /^date|date$/ ? format_date($item_info->{$_}) : $item_info->{$_} || '' } @item_content_fields;
Lines 286-292 UPCOMINGITEM: foreach my $upcoming ( @$upcoming_dues ) { Link Here
286
        } else {
326
        } else {
287
            my $biblio = C4::Biblio::GetBiblioFromItemNumber( $upcoming->{'itemnumber'} );
327
            my $biblio = C4::Biblio::GetBiblioFromItemNumber( $upcoming->{'itemnumber'} );
288
            my $letter_type = 'PREDUE';
328
            my $letter_type = 'PREDUE';
289
            $sth->execute($upcoming->{'borrowernumber'},$upcoming->{'itemnumber'},$borrower_preferences->{'days_in_advance'});
329
            $sth->execute($upcoming->{'borrowernumber'},$upcoming->{'itemnumber'},$date_in_history,$borrower_preferences->{'days_in_advance'});
290
            my $titles = "";
330
            my $titles = "";
291
            while ( my $item_info = $sth->fetchrow_hashref()) {
331
            while ( my $item_info = $sth->fetchrow_hashref()) {
292
              my @item_info = map { $_ =~ /^date|date$/ ? format_date($item_info->{$_}) : $item_info->{$_} || '' } @item_content_fields;
332
              my @item_info = map { $_ =~ /^date|date$/ ? format_date($item_info->{$_}) : $item_info->{$_} || '' } @item_content_fields;
Lines 339-345 SELECT biblio.*, items.*, issues.* Link Here
339
  WHERE items.itemnumber=issues.itemnumber
379
  WHERE items.itemnumber=issues.itemnumber
340
    AND biblio.biblionumber=items.biblionumber
380
    AND biblio.biblionumber=items.biblionumber
341
    AND issues.borrowernumber = ?
381
    AND issues.borrowernumber = ?
342
    AND (TO_DAYS(date_due)-TO_DAYS(NOW()) = ?)
382
    AND (TO_DAYS(date_due)-TO_DAYS(?) = ?)
343
END_SQL
383
END_SQL
344
PATRON: while ( my ( $borrowernumber, $digest ) = each %$upcoming_digest ) {
384
PATRON: while ( my ( $borrowernumber, $digest ) = each %$upcoming_digest ) {
345
    @letters = ();
385
    @letters = ();
Lines 354-360 PATRON: while ( my ( $borrowernumber, $digest ) = each %$upcoming_digest ) { Link Here
354
394
355
    my $letter_type = 'PREDUEDGST';
395
    my $letter_type = 'PREDUEDGST';
356
396
357
    $sth->execute($borrowernumber,$borrower_preferences->{'days_in_advance'});
397
    $sth->execute($borrowernumber,$date_in_history,$borrower_preferences->{'days_in_advance'});
358
    my $titles = "";
398
    my $titles = "";
359
    while ( my $item_info = $sth->fetchrow_hashref()) {
399
    while ( my $item_info = $sth->fetchrow_hashref()) {
360
      my @item_info = map { $_ =~ /^date|date$/ ? format_date($item_info->{$_}) : $item_info->{$_} || '' } @item_content_fields;
400
      my @item_info = map { $_ =~ /^date|date$/ ? format_date($item_info->{$_}) : $item_info->{$_} || '' } @item_content_fields;
Lines 412-418 PATRON: while ( my ( $borrowernumber, $digest ) = each %$due_digest ) { Link Here
412
    next PATRON unless $borrower_preferences; # how could this happen?
452
    next PATRON unless $borrower_preferences; # how could this happen?
413
453
414
    my $letter_type = 'DUEDGST';
454
    my $letter_type = 'DUEDGST';
415
    $sth->execute($borrowernumber,'0');
455
    $sth->execute($borrowernumber,$date_in_history,'0');
416
    my $titles = "";
456
    my $titles = "";
417
    while ( my $item_info = $sth->fetchrow_hashref()) {
457
    while ( my $item_info = $sth->fetchrow_hashref()) {
418
      my @item_info = map { $_ =~ /^date|date$/ ? format_date($item_info->{$_}) : $item_info->{$_} || '' } @item_content_fields;
458
      my @item_info = map { $_ =~ /^date|date$/ ? format_date($item_info->{$_}) : $item_info->{$_} || '' } @item_content_fields;
419
- 

Return to bug 12924