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

(-)a/C4/Letters.pm (-1 / +8 lines)
Lines 576-586 sub SendAlerts { Link Here
576
        $letter->{content} =~ s/<order>(.*?)<\/order>/$1/gxms;
576
        $letter->{content} =~ s/<order>(.*?)<\/order>/$1/gxms;
577
577
578
        # ... then send mail
578
        # ... then send mail
579
        my $from;
579
        my $library = Koha::Libraries->find( $userenv->{branch} );
580
        my $library = Koha::Libraries->find( $userenv->{branch} );
581
        if ($library and $library->branchemail) {
582
            $from = $library->branchemail;
583
        } else {
584
            $from = C4::Context->preference('KohaAdminEmailAddress');
585
        }
586
580
        my %mail = (
587
        my %mail = (
581
            To => join( ',', @email),
588
            To => join( ',', @email),
582
            Cc             => join( ',', @cc),
589
            Cc             => join( ',', @cc),
583
            From           => $library->branchemail || C4::Context->preference('KohaAdminEmailAddress'),
590
            From           => $from,
584
            Subject        => Encode::encode( "UTF-8", "" . $letter->{title} ),
591
            Subject        => Encode::encode( "UTF-8", "" . $letter->{title} ),
585
            Message => $letter->{'is_html'}
592
            Message => $letter->{'is_html'}
586
                            ? _wrap_html( Encode::encode( "UTF-8", $letter->{'content'} ),
593
                            ? _wrap_html( Encode::encode( "UTF-8", $letter->{'content'} ),
(-)a/C4/Serials.pm (-12 / +18 lines)
Lines 343-349 sub GetFullSubscription { Link Here
343
    my $sth = $dbh->prepare($query);
343
    my $sth = $dbh->prepare($query);
344
    $sth->execute($subscriptionid);
344
    $sth->execute($subscriptionid);
345
    my $subscriptions = $sth->fetchall_arrayref( {} );
345
    my $subscriptions = $sth->fetchall_arrayref( {} );
346
    my $cannotedit = not can_edit_subscription( $subscriptions->[0] ) if scalar @$subscriptions;
346
    my $cannotedit;
347
    $cannotedit = not can_edit_subscription( $subscriptions->[0] ) if scalar @$subscriptions;
347
    for my $subscription ( @$subscriptions ) {
348
    for my $subscription ( @$subscriptions ) {
348
        $subscription->{cannotedit} = $cannotedit;
349
        $subscription->{cannotedit} = $cannotedit;
349
    }
350
    }
Lines 366-374 sub PrepareSerialsData { Link Here
366
    my $year;
367
    my $year;
367
    my @res;
368
    my @res;
368
    my $startdate;
369
    my $startdate;
369
    my $aqbooksellername;
370
    my $bibliotitle;
371
    my @loopissues;
372
    my $first;
370
    my $first;
373
    my $previousnote = "";
371
    my $previousnote = "";
374
372
Lines 503-509 sub GetFullSubscriptionsFromBiblionumber { Link Here
503
    my $sth = $dbh->prepare($query);
501
    my $sth = $dbh->prepare($query);
504
    $sth->execute($biblionumber);
502
    $sth->execute($biblionumber);
505
    my $subscriptions = $sth->fetchall_arrayref( {} );
503
    my $subscriptions = $sth->fetchall_arrayref( {} );
506
    my $cannotedit = not can_edit_subscription( $subscriptions->[0] ) if scalar @$subscriptions;
504
    my $cannotedit;
505
    $cannotedit = not can_edit_subscription( $subscriptions->[0] ) if scalar @$subscriptions;
507
    for my $subscription ( @$subscriptions ) {
506
    for my $subscription ( @$subscriptions ) {
508
        $subscription->{cannotedit} = $cannotedit;
507
        $subscription->{cannotedit} = $cannotedit;
509
    }
508
    }
Lines 1348-1356 sub ModSubscription { Link Here
1348
    $biblionumber, $callnumber, $notes, $letter, $manualhistory,
1347
    $biblionumber, $callnumber, $notes, $letter, $manualhistory,
1349
    $internalnotes, $serialsadditems, $staffdisplaycount, $opacdisplaycount,
1348
    $internalnotes, $serialsadditems, $staffdisplaycount, $opacdisplaycount,
1350
    $graceperiod, $location, $enddate, $subscriptionid, $skip_serialseq,
1349
    $graceperiod, $location, $enddate, $subscriptionid, $skip_serialseq,
1351
    $itemtype, $previousitemtype
1350
    $itemtype, $previousitemtype, $auto_claim_enabled
1352
    ) = @_;
1351
    ) = @_;
1353
1352
1353
    $auto_claim_enabled //= 0;
1354
1354
    my $dbh   = C4::Context->dbh;
1355
    my $dbh   = C4::Context->dbh;
1355
    my $query = "UPDATE subscription
1356
    my $query = "UPDATE subscription
1356
        SET librarian=?, branchcode=?, aqbooksellerid=?, cost=?, aqbudgetid=?,
1357
        SET librarian=?, branchcode=?, aqbooksellerid=?, cost=?, aqbudgetid=?,
Lines 1361-1367 sub ModSubscription { Link Here
1361
            callnumber=?, notes=?, letter=?, manualhistory=?,
1362
            callnumber=?, notes=?, letter=?, manualhistory=?,
1362
            internalnotes=?, serialsadditems=?, staffdisplaycount=?,
1363
            internalnotes=?, serialsadditems=?, staffdisplaycount=?,
1363
            opacdisplaycount=?, graceperiod=?, location = ?, enddate=?,
1364
            opacdisplaycount=?, graceperiod=?, location = ?, enddate=?,
1364
            skip_serialseq=?, itemtype=?, previousitemtype=?
1365
            skip_serialseq=?, itemtype=?, previousitemtype=?,
1366
            auto_claim_enabled=?
1365
        WHERE subscriptionid = ?";
1367
        WHERE subscriptionid = ?";
1366
1368
1367
    my $sth = $dbh->prepare($query);
1369
    my $sth = $dbh->prepare($query);
Lines 1375-1381 sub ModSubscription { Link Here
1375
        $letter,          ($manualhistory ? $manualhistory : 0),
1377
        $letter,          ($manualhistory ? $manualhistory : 0),
1376
        $internalnotes, $serialsadditems, $staffdisplaycount, $opacdisplaycount,
1378
        $internalnotes, $serialsadditems, $staffdisplaycount, $opacdisplaycount,
1377
        $graceperiod,     $location,       $enddate,        $skip_serialseq,
1379
        $graceperiod,     $location,       $enddate,        $skip_serialseq,
1378
        $itemtype,        $previousitemtype,
1380
        $itemtype,        $previousitemtype, $auto_claim_enabled,
1379
        $subscriptionid
1381
        $subscriptionid
1380
    );
1382
    );
1381
    my $rows = $sth->rows;
1383
    my $rows = $sth->rows;
Lines 1409-1416 sub NewSubscription { Link Here
1409
    $innerloop3, $status, $notes, $letter, $firstacquidate, $irregularity,
1411
    $innerloop3, $status, $notes, $letter, $firstacquidate, $irregularity,
1410
    $numberpattern, $locale, $callnumber, $manualhistory, $internalnotes,
1412
    $numberpattern, $locale, $callnumber, $manualhistory, $internalnotes,
1411
    $serialsadditems, $staffdisplaycount, $opacdisplaycount, $graceperiod,
1413
    $serialsadditems, $staffdisplaycount, $opacdisplaycount, $graceperiod,
1412
    $location, $enddate, $skip_serialseq, $itemtype, $previousitemtype
1414
    $location, $enddate, $skip_serialseq, $itemtype, $previousitemtype,
1415
    $auto_claim_enabled
1413
    ) = @_;
1416
    ) = @_;
1417
1418
    $auto_claim_enabled //= 0;
1419
1414
    my $dbh = C4::Context->dbh;
1420
    my $dbh = C4::Context->dbh;
1415
1421
1416
    #save subscription (insert into database)
1422
    #save subscription (insert into database)
Lines 1423-1430 sub NewSubscription { Link Here
1423
            irregularity, numberpattern, locale, callnumber,
1429
            irregularity, numberpattern, locale, callnumber,
1424
            manualhistory, internalnotes, serialsadditems, staffdisplaycount,
1430
            manualhistory, internalnotes, serialsadditems, staffdisplaycount,
1425
            opacdisplaycount, graceperiod, location, enddate, skip_serialseq,
1431
            opacdisplaycount, graceperiod, location, enddate, skip_serialseq,
1426
            itemtype, previousitemtype)
1432
            itemtype, previousitemtype, auto_claim_enabled)
1427
        VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
1433
        VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
1428
        |;
1434
        |;
1429
    my $sth = $dbh->prepare($query);
1435
    my $sth = $dbh->prepare($query);
1430
    $sth->execute(
1436
    $sth->execute(
Lines 1435-1441 sub NewSubscription { Link Here
1435
        $firstacquidate, $irregularity, $numberpattern, $locale, $callnumber,
1441
        $firstacquidate, $irregularity, $numberpattern, $locale, $callnumber,
1436
        $manualhistory, $internalnotes, $serialsadditems, $staffdisplaycount,
1442
        $manualhistory, $internalnotes, $serialsadditems, $staffdisplaycount,
1437
        $opacdisplaycount, $graceperiod, $location, $enddate, $skip_serialseq,
1443
        $opacdisplaycount, $graceperiod, $location, $enddate, $skip_serialseq,
1438
        $itemtype, $previousitemtype
1444
        $itemtype, $previousitemtype, $auto_claim_enabled
1439
    );
1445
    );
1440
1446
1441
    my $subscriptionid = $dbh->{'mysql_insertid'};
1447
    my $subscriptionid = $dbh->{'mysql_insertid'};
(-)a/installer/data/mysql/atomicupdate/bug_18783.perl (+12 lines)
Line 0 Link Here
1
$DBversion = 'XXX';
2
if ( CheckVersion($DBversion) ) {
3
    if ( !column_exists('subscription', 'auto_claim_enabled') ) {
4
        $dbh->do(q{
5
            ALTER TABLE subscription
6
            ADD COLUMN auto_claim_enabled tinyint NOT NULL DEFAULT 0 AFTER previousitemtype
7
        });
8
    }
9
10
    SetVersion($DBversion);
11
    print "Upgrade to $DBversion done (Bug 18783 - Automatic claims for serials)\n";
12
}
(-)a/installer/data/mysql/kohastructure.sql (+1 lines)
Lines 2123-2128 CREATE TABLE `subscription` ( -- information related to the subscription Link Here
2123
  `reneweddate` date default NULL, -- date of last renewal for the subscription
2123
  `reneweddate` date default NULL, -- date of last renewal for the subscription
2124
  `itemtype` VARCHAR( 10 ) NULL,
2124
  `itemtype` VARCHAR( 10 ) NULL,
2125
  `previousitemtype` VARCHAR( 10 ) NULL,
2125
  `previousitemtype` VARCHAR( 10 ) NULL,
2126
  `auto_claim_enabled` tinyint NOT NULL DEFAULT 0, -- enable automatic claiming
2126
  PRIMARY KEY  (`subscriptionid`),
2127
  PRIMARY KEY  (`subscriptionid`),
2127
  CONSTRAINT subscription_ibfk_1 FOREIGN KEY (periodicity) REFERENCES subscription_frequencies (id) ON DELETE SET NULL ON UPDATE CASCADE,
2128
  CONSTRAINT subscription_ibfk_1 FOREIGN KEY (periodicity) REFERENCES subscription_frequencies (id) ON DELETE SET NULL ON UPDATE CASCADE,
2128
  CONSTRAINT subscription_ibfk_2 FOREIGN KEY (numberpattern) REFERENCES subscription_numberpatterns (id) ON DELETE SET NULL ON UPDATE CASCADE
2129
  CONSTRAINT subscription_ibfk_2 FOREIGN KEY (numberpattern) REFERENCES subscription_numberpatterns (id) ON DELETE SET NULL ON UPDATE CASCADE
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/serials/subscription-add.tt (+8 lines)
Lines 684-689 $(document).ready(function() { Link Here
684
                                    <input type="text" name="graceperiod" id="graceperiod" value="[% graceperiod %]" size="5"/> day(s)
684
                                    <input type="text" name="graceperiod" id="graceperiod" value="[% graceperiod %]" size="5"/> day(s)
685
                                </li>
685
                                </li>
686
                                <li>
686
                                <li>
687
                                    <label for="auto_claim_enabled">Enable automatic claims</label>
688
                                    [% IF auto_claim_enabled %]
689
                                        <input type="checkbox" name="auto_claim_enabled" id="auto_claim_enabled" value="1" checked/>
690
                                    [% ELSE %]
691
                                        <input type="checkbox" name="auto_claim_enabled" id="auto_claim_enabled" value="1"/>
692
                                    [% END %]
693
                                </li>
694
                                <li>
687
                                     <label class="widelabel" for="staffdisplaycount">Number of issues to display to staff: </label>
695
                                     <label class="widelabel" for="staffdisplaycount">Number of issues to display to staff: </label>
688
                                     <input type="text" name="staffdisplaycount" id="staffdisplaycount" value="[% staffdisplaycount %]" size="4"/>
696
                                     <input type="text" name="staffdisplaycount" id="staffdisplaycount" value="[% staffdisplaycount %]" size="4"/>
689
                                 </li>
697
                                 </li>
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/serials/subscription-detail.tt (+1 lines)
Lines 110-115 $(document).ready(function() { Link Here
110
            [% END %]
110
            [% END %]
111
        </li>
111
        </li>
112
        <li><span class="label">Grace period:</span> [% graceperiod %]</li>
112
        <li><span class="label">Grace period:</span> [% graceperiod %]</li>
113
        <li><span class="label">Automatic claims:</span> [% IF auto_claim_enabled %]Enabled[% ELSE %]Disabled[% END %]</li>
113
        </ol>
114
        </ol>
114
    </div>
115
    </div>
115
    </div>
116
    </div>
(-)a/misc/cronjobs/serialsClaim.pl (+117 lines)
Line 0 Link Here
1
#!/usr/bin/perl
2
3
# Copyright 2017 Biblibre
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
=head1 NAME
21
22
serialsClaims.pl - Send claim notice to suppliers that have late or missing issues
23
24
=head1 SYNOPSIS
25
26
serialsClaims.pl --letter-code LETTER_CODE [--max-claims MAX_CLAIMS]
27
28
Options:
29
    --letter-code LETTER_CODE   Mandatory. Use letter LETTER_CODE.
30
    --max-claims MAX_CLAIMS     Send up to MAX_CLAIMS notices
31
32
=cut
33
34
use Modern::Perl;
35
36
use DateTime;
37
use Getopt::Long;
38
39
use Koha::Acquisition::Booksellers;
40
use Koha::DateUtils;
41
use Koha::Subscriptions;
42
43
use C4::Context;
44
use C4::Letters;
45
use C4::Serials;
46
47
sub usage {
48
    return <<EOT
49
Usage: $0 --letter-code LETTER_CODE [--max-claims MAX_CLAIMS]
50
EOT
51
}
52
53
my $letter_code;
54
my $max_claims;
55
56
GetOptions(
57
    'letter-code=s' => \$letter_code,
58
    'max-claims=i' => \$max_claims,
59
) or die usage();
60
61
die usage() unless $letter_code;
62
63
my $suppliers = GetSuppliersWithLateIssues();
64
foreach my $supplier (@$suppliers) {
65
    my $bookseller = Koha::Acquisition::Booksellers->find($supplier->{id});
66
    my $supplierinfo = $bookseller->name . ' (' . $bookseller->id . ')';
67
68
    my $deliverytime = $bookseller->deliverytime;
69
    unless ($deliverytime) {
70
        say STDERR "Warning: There is no delivery time set for supplier $supplierinfo. Automatic claiming is disabled for this supplier.";
71
        next;
72
    }
73
74
    my @serials = GetLateOrMissingIssues($bookseller->id);
75
    my @serialids;
76
    foreach my $serial (@serials) {
77
        if ($max_claims && $serial->{claims_count} >= $max_claims) {
78
            say "Maximum claims count reached for serial " . $serial->{serialid};
79
            next;
80
        }
81
82
        my $subscription = Koha::Subscriptions->find($serial->{subscriptionid});
83
        next unless $subscription->auto_claim_enabled;
84
85
        my $claims_count = $serial->{claims_count};
86
        my $date = $serial->{claimdate} ? $serial->{claimdate} : $serial->{planneddate};
87
        my $newclaimdate = dt_from_string($date)->add(days => $deliverytime);
88
        my $now = DateTime->now(time_zone => C4::Context->tz);
89
90
        if ($newclaimdate <= $now) {
91
            push @serialids, $serial->{serialid};
92
        }
93
    }
94
95
    if (@serialids) {
96
        my $err;
97
        eval {
98
            $err = SendAlerts('claimissues', \@serialids, $letter_code);
99
            if ( not ref $err or not exists $err->{error} ) {
100
                C4::Serials::updateClaim( \@serialids );
101
            }
102
        };
103
        if ( $@ ) {
104
            say STDERR "Error: $@ while claiming serials " . join(',', @serialids);
105
        } elsif ( ref $err and exists $err->{error} ) {
106
            if ( $err->{error} eq "no_email" ) {
107
                say STDERR "Error: Supplier $supplierinfo has no email";
108
            } elsif ( $err->{error} =~ m|Bad or missing From address| ) {
109
                say STDERR "Error: Supplier $supplierinfo has no email";
110
            } else {
111
                say STDERR "Error: " . $err->{error};
112
            }
113
        } else {
114
            say "Claim sent to $supplierinfo for serials " . join(',', @serialids);
115
        }
116
    }
117
}
(-)a/serials/subscription-add.pl (-2 / +4 lines)
Lines 321-326 sub redirect_add_subscription { Link Here
321
    my $itemtype          = $query->param('itemtype');
321
    my $itemtype          = $query->param('itemtype');
322
    my $previousitemtype  = $query->param('previousitemtype');
322
    my $previousitemtype  = $query->param('previousitemtype');
323
    my $skip_serialseq    = $query->param('skip_serialseq');
323
    my $skip_serialseq    = $query->param('skip_serialseq');
324
    my $auto_claim_enabled = $query->param('auto_claim_enabled');
324
325
325
    my $startdate      = output_pref( { str => scalar $query->param('startdate'),      dateonly => 1, dateformat => 'iso' } );
326
    my $startdate      = output_pref( { str => scalar $query->param('startdate'),      dateonly => 1, dateformat => 'iso' } );
326
    my $enddate        = output_pref( { str => scalar $query->param('enddate'),        dateonly => 1, dateformat => 'iso' } );
327
    my $enddate        = output_pref( { str => scalar $query->param('enddate'),        dateonly => 1, dateformat => 'iso' } );
Lines 342-348 sub redirect_add_subscription { Link Here
342
        join(";",@irregularity), $numberpattern, $locale, $callnumber,
343
        join(";",@irregularity), $numberpattern, $locale, $callnumber,
343
        $manualhistory, $internalnotes, $serialsadditems,
344
        $manualhistory, $internalnotes, $serialsadditems,
344
        $staffdisplaycount, $opacdisplaycount, $graceperiod, $location, $enddate,
345
        $staffdisplaycount, $opacdisplaycount, $graceperiod, $location, $enddate,
345
        $skip_serialseq
346
        $skip_serialseq, undef, undef, $auto_claim_enabled
346
    );
347
    );
347
348
348
    my $additional_fields = Koha::AdditionalField->all( { tablename => 'subscription' } );
349
    my $additional_fields = Koha::AdditionalField->all( { tablename => 'subscription' } );
Lines 400-405 sub redirect_mod_subscription { Link Here
400
    my $itemtype          = $query->param('itemtype');
401
    my $itemtype          = $query->param('itemtype');
401
    my $previousitemtype  = $query->param('previousitemtype');
402
    my $previousitemtype  = $query->param('previousitemtype');
402
    my $skip_serialseq    = $query->param('skip_serialseq');
403
    my $skip_serialseq    = $query->param('skip_serialseq');
404
    my $auto_claim_enabled = $query->param('auto_claim_enabled');
403
405
404
    # Guess end date
406
    # Guess end date
405
    if(!defined $enddate || $enddate eq '') {
407
    if(!defined $enddate || $enddate eq '') {
Lines 426-432 sub redirect_mod_subscription { Link Here
426
        $status, $biblionumber, $callnumber, $notes, $letter,
428
        $status, $biblionumber, $callnumber, $notes, $letter,
427
        $manualhistory, $internalnotes, $serialsadditems, $staffdisplaycount,
429
        $manualhistory, $internalnotes, $serialsadditems, $staffdisplaycount,
428
        $opacdisplaycount, $graceperiod, $location, $enddate, $subscriptionid,
430
        $opacdisplaycount, $graceperiod, $location, $enddate, $subscriptionid,
429
        $skip_serialseq, $itemtype, $previousitemtype
431
        $skip_serialseq, $itemtype, $previousitemtype, $auto_claim_enabled
430
    );
432
    );
431
433
432
    my $additional_fields = Koha::AdditionalField->all( { tablename => 'subscription' } );
434
    my $additional_fields = Koha::AdditionalField->all( { tablename => 'subscription' } );
(-)a/t/db_dependent/Serials.t (-5 / +12 lines)
Lines 355-364 $dbh->rollback; Link Here
355
355
356
sub get_biblio {
356
sub get_biblio {
357
    my $bib = MARC::Record->new();
357
    my $bib = MARC::Record->new();
358
    $bib->append_fields(
358
359
        MARC::Field->new('100', ' ', ' ', a => 'Moffat, Steven'),
359
    if (C4::Context->preference('marcflavour') eq 'UNIMARC') {
360
        MARC::Field->new('245', ' ', ' ', a => 'Silence in the library'),
360
        $bib->append_fields(
361
    );
361
            MARC::Field->new('200', ' ', ' ', f => 'Moffat, Steven'),
362
            MARC::Field->new('200', ' ', ' ', a => 'Silence in the library'),
363
        );
364
    } else {
365
        $bib->append_fields(
366
            MARC::Field->new('100', ' ', ' ', a => 'Moffat, Steven'),
367
            MARC::Field->new('245', ' ', ' ', a => 'Silence in the library'),
368
        );
369
    }
362
    my ($bibnum, $bibitemnum) = AddBiblio($bib, '');
370
    my ($bibnum, $bibitemnum) = AddBiblio($bib, '');
363
    return ($bibnum, $bibitemnum);
371
    return ($bibnum, $bibitemnum);
364
}
372
}
365
- 

Return to bug 18783