From 12f12272cdb1170dd422d70a0bb78b0def664c18 Mon Sep 17 00:00:00 2001 From: Julian Maurice Date: Mon, 12 Jun 2017 11:51:43 +0200 Subject: [PATCH] Bug 18783: Allow automatic claims for serials This patch adds a new script misc/cronjobs/serialsClaim.pl which send email notification to all suppliers that have late or missing issues. This is configurable per subscription and is disabled by default. Test plan: 1. Create a new bookseller B1 with a delivery time of 5 days 2. Create a new daily subscription with bookseller B1 and enable automatic claims (new checkbox on the first page of subscription-add.pl) 3. Generate some late serials with an expected date in the past (some with more than 5 days in the past, some with less) 4. Create a notice for module "Claim serial issue" CLAIMSERIAL and write something in the 'Email' template 5. Run `misc/cronjobs/serialsClaims.pl --letter-code CLAIMSERIAL` and verify that it sends an email notification only for serials that were expected more than 5 days ago --- C4/Letters.pm | 9 +- C4/Serials.pm | 25 ++-- .../data/mysql/atomicupdate/bug_18783.perl | 12 ++ installer/data/mysql/kohastructure.sql | 1 + .../en/modules/serials/subscription-add.tt | 8 ++ .../en/modules/serials/subscription-detail.tt | 1 + misc/cronjobs/serialsClaim.pl | 117 ++++++++++++++++++ serials/subscription-add.pl | 6 +- 8 files changed, 166 insertions(+), 13 deletions(-) create mode 100644 installer/data/mysql/atomicupdate/bug_18783.perl create mode 100755 misc/cronjobs/serialsClaim.pl diff --git a/C4/Letters.pm b/C4/Letters.pm index bdb213a49e..0a5eeb729d 100644 --- a/C4/Letters.pm +++ b/C4/Letters.pm @@ -479,7 +479,13 @@ sub SendAlerts { $letter->{content} =~ s/(.*?)<\/order>/$1/gxms; # ... then send mail + my $from; my $library = Koha::Libraries->find( $userenv->{branch} ); + if ($library and $library->branchemail) { + $from = $library->branchemail; + } else { + $from = C4::Context->preference('KohaAdminEmailAddress'); + } my $email = Koha::Email->new(); my %mail = $email->create_message_headers( { @@ -493,8 +499,7 @@ sub SendAlerts { ) ? ( bcc => $userenv->{emailaddress} ) : () ), - from => $library->branchemail - || C4::Context->preference('KohaAdminEmailAddress'), + from => $from, subject => Encode::encode( "UTF-8", "" . $letter->{title} ), message => $letter->{'is_html'} ? _wrap_html( Encode::encode( "UTF-8", $letter->{'content'} ), diff --git a/C4/Serials.pm b/C4/Serials.pm index 6bdbd8cc4e..f2435e1bd5 100644 --- a/C4/Serials.pm +++ b/C4/Serials.pm @@ -323,7 +323,8 @@ sub GetFullSubscription { my $sth = $dbh->prepare($query); $sth->execute($subscriptionid); my $subscriptions = $sth->fetchall_arrayref( {} ); - my $cannotedit = not can_edit_subscription( $subscriptions->[0] ) if scalar @$subscriptions; + my $cannotedit; + $cannotedit = not can_edit_subscription( $subscriptions->[0] ) if scalar @$subscriptions; for my $subscription ( @$subscriptions ) { $subscription->{cannotedit} = $cannotedit; } @@ -346,9 +347,6 @@ sub PrepareSerialsData { my $year; my @res; my $startdate; - my $aqbooksellername; - my $bibliotitle; - my @loopissues; my $first; my $previousnote = ""; @@ -481,7 +479,8 @@ sub GetFullSubscriptionsFromBiblionumber { my $sth = $dbh->prepare($query); $sth->execute($biblionumber); my $subscriptions = $sth->fetchall_arrayref( {} ); - my $cannotedit = not can_edit_subscription( $subscriptions->[0] ) if scalar @$subscriptions; + my $cannotedit; + $cannotedit = not can_edit_subscription( $subscriptions->[0] ) if scalar @$subscriptions; for my $subscription ( @$subscriptions ) { $subscription->{cannotedit} = $cannotedit; } @@ -1301,9 +1300,11 @@ sub ModSubscription { $biblionumber, $callnumber, $notes, $letter, $manualhistory, $internalnotes, $serialsadditems, $staffdisplaycount, $opacdisplaycount, $graceperiod, $location, $enddate, $subscriptionid, $skip_serialseq, - $itemtype, $previousitemtype, $mana_id + $itemtype, $previousitemtype, $mana_id, $auto_claim_enabled ) = @_; + $auto_claim_enabled //= 0; + my $dbh = C4::Context->dbh; my $query = "UPDATE subscription SET librarian=?, branchcode=?, aqbooksellerid=?, cost=?, aqbudgetid=?, @@ -1314,7 +1315,8 @@ sub ModSubscription { callnumber=?, notes=?, letter=?, manualhistory=?, internalnotes=?, serialsadditems=?, staffdisplaycount=?, opacdisplaycount=?, graceperiod=?, location = ?, enddate=?, - skip_serialseq=?, itemtype=?, previousitemtype=?, mana_id=? + skip_serialseq=?, itemtype=?, previousitemtype=?, mana_id=?, + auto_claim_enabled=? WHERE subscriptionid = ?"; my $sth = $dbh->prepare($query); @@ -1328,7 +1330,7 @@ sub ModSubscription { $letter, ($manualhistory ? $manualhistory : 0), $internalnotes, $serialsadditems, $staffdisplaycount, $opacdisplaycount, $graceperiod, $location, $enddate, $skip_serialseq, - $itemtype, $previousitemtype, $mana_id, + $itemtype, $previousitemtype, $mana_id, $auto_claim_enabled, $subscriptionid ); my $rows = $sth->rows; @@ -1362,8 +1364,12 @@ sub NewSubscription { $innerloop3, $status, $notes, $letter, $firstacquidate, $irregularity, $numberpattern, $locale, $callnumber, $manualhistory, $internalnotes, $serialsadditems, $staffdisplaycount, $opacdisplaycount, $graceperiod, - $location, $enddate, $skip_serialseq, $itemtype, $previousitemtype, $mana_id + $location, $enddate, $skip_serialseq, $itemtype, $previousitemtype, $mana_id, + $auto_claim_enabled ) = @_; + + $auto_claim_enabled //= 0; + my $dbh = C4::Context->dbh; my $subscription = Koha::Subscription->new( @@ -1405,6 +1411,7 @@ sub NewSubscription { itemtype => $itemtype, previousitemtype => $previousitemtype, mana_id => $mana_id, + auto_claim_enabled => $auto_claim_enabled, } )->store; $subscription->discard_changes; diff --git a/installer/data/mysql/atomicupdate/bug_18783.perl b/installer/data/mysql/atomicupdate/bug_18783.perl new file mode 100644 index 0000000000..6ed890456e --- /dev/null +++ b/installer/data/mysql/atomicupdate/bug_18783.perl @@ -0,0 +1,12 @@ +$DBversion = 'XXX'; +if ( CheckVersion($DBversion) ) { + if ( !column_exists('subscription', 'auto_claim_enabled') ) { + $dbh->do(q{ + ALTER TABLE subscription + ADD COLUMN auto_claim_enabled tinyint NOT NULL DEFAULT 0 AFTER previousitemtype + }); + } + + SetVersion($DBversion); + print "Upgrade to $DBversion done (Bug 18783 - Automatic claims for serials)\n"; +} diff --git a/installer/data/mysql/kohastructure.sql b/installer/data/mysql/kohastructure.sql index 9b062d0800..5865ccf242 100644 --- a/installer/data/mysql/kohastructure.sql +++ b/installer/data/mysql/kohastructure.sql @@ -2032,6 +2032,7 @@ CREATE TABLE `subscription` ( -- information related to the subscription `itemtype` VARCHAR( 10 ) NULL, `previousitemtype` VARCHAR( 10 ) NULL, `mana_id` int(11) NULL DEFAULT NULL, + `auto_claim_enabled` tinyint NOT NULL DEFAULT 0, -- enable automatic claiming PRIMARY KEY (`subscriptionid`), KEY `by_biblionumber` (`biblionumber`), CONSTRAINT subscription_ibfk_1 FOREIGN KEY (periodicity) REFERENCES subscription_frequencies (id) ON DELETE SET NULL ON UPDATE CASCADE, diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/serials/subscription-add.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/serials/subscription-add.tt index eff55ae7da..698feb552e 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/serials/subscription-add.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/serials/subscription-add.tt @@ -201,6 +201,14 @@ fieldset.rows table { clear: none; margin: 0; } day(s) +
  • + + [% IF auto_claim_enabled %] + + [% ELSE %] + + [% END %] +
  • diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/serials/subscription-detail.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/serials/subscription-detail.tt index 983a7a8056..86dab8799f 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/serials/subscription-detail.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/serials/subscription-detail.tt @@ -110,6 +110,7 @@ [% END %]
  • Grace period: [% graceperiod | html %]
  • +
  • Automatic claims: [% IF auto_claim_enabled %]Enabled[% ELSE %]Disabled[% END %]
  • diff --git a/misc/cronjobs/serialsClaim.pl b/misc/cronjobs/serialsClaim.pl new file mode 100755 index 0000000000..3995f29dea --- /dev/null +++ b/misc/cronjobs/serialsClaim.pl @@ -0,0 +1,117 @@ +#!/usr/bin/perl + +# Copyright 2017 Biblibre +# +# This file is part of Koha. +# +# Koha is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# Koha is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Koha; if not, see . + +=head1 NAME + +serialsClaims.pl - Send claim notice to suppliers that have late or missing issues + +=head1 SYNOPSIS + +serialsClaims.pl --letter-code LETTER_CODE [--max-claims MAX_CLAIMS] + +Options: + --letter-code LETTER_CODE Mandatory. Use letter LETTER_CODE. + --max-claims MAX_CLAIMS Send up to MAX_CLAIMS notices + +=cut + +use Modern::Perl; + +use DateTime; +use Getopt::Long; + +use Koha::Acquisition::Booksellers; +use Koha::DateUtils; +use Koha::Subscriptions; + +use C4::Context; +use C4::Letters; +use C4::Serials; + +sub usage { + return < \$letter_code, + 'max-claims=i' => \$max_claims, +) or die usage(); + +die usage() unless $letter_code; + +my $suppliers = GetSuppliersWithLateIssues(); +foreach my $supplier (@$suppliers) { + my $bookseller = Koha::Acquisition::Booksellers->find($supplier->{id}); + my $supplierinfo = $bookseller->name . ' (' . $bookseller->id . ')'; + + my $deliverytime = $bookseller->deliverytime; + unless ($deliverytime) { + say STDERR "Warning: There is no delivery time set for supplier $supplierinfo. Automatic claiming is disabled for this supplier."; + next; + } + + my @serials = GetLateOrMissingIssues($bookseller->id); + my @serialids; + foreach my $serial (@serials) { + if ($max_claims && $serial->{claims_count} >= $max_claims) { + say "Maximum claims count reached for serial " . $serial->{serialid}; + next; + } + + my $subscription = Koha::Subscriptions->find($serial->{subscriptionid}); + next unless $subscription->auto_claim_enabled; + + my $claims_count = $serial->{claims_count}; + my $date = $serial->{claimdate} ? $serial->{claimdate} : $serial->{planneddate}; + my $newclaimdate = dt_from_string($date)->add(days => $deliverytime); + my $now = DateTime->now(time_zone => C4::Context->tz); + + if ($newclaimdate <= $now) { + push @serialids, $serial->{serialid}; + } + } + + if (@serialids) { + my $err; + eval { + $err = SendAlerts('claimissues', \@serialids, $letter_code); + if ( not ref $err or not exists $err->{error} ) { + C4::Serials::updateClaim( \@serialids ); + } + }; + if ( $@ ) { + say STDERR "Error: $@ while claiming serials " . join(',', @serialids); + } elsif ( ref $err and exists $err->{error} ) { + if ( $err->{error} eq "no_email" ) { + say STDERR "Error: Supplier $supplierinfo has no email"; + } elsif ( $err->{error} =~ m|Bad or missing From address| ) { + say STDERR "Error: Supplier $supplierinfo has no email"; + } else { + say STDERR "Error: " . $err->{error}; + } + } else { + say "Claim sent to $supplierinfo for serials " . join(',', @serialids); + } + } +} diff --git a/serials/subscription-add.pl b/serials/subscription-add.pl index ebc19a05e9..0c0aa8aec2 100755 --- a/serials/subscription-add.pl +++ b/serials/subscription-add.pl @@ -349,6 +349,7 @@ sub redirect_add_subscription { my $itemtype = $query->param('itemtype'); my $previousitemtype = $query->param('previousitemtype'); my $skip_serialseq = $query->param('skip_serialseq'); + my $auto_claim_enabled = $query->param('auto_claim_enabled'); my $mana_id; if ( $query->param('mana_id') ne "" ) { @@ -375,7 +376,7 @@ sub redirect_add_subscription { join(";",@irregularity), $numberpattern, $locale, $callnumber, $manualhistory, $internalnotes, $serialsadditems, $staffdisplaycount, $opacdisplaycount, $graceperiod, $location, $enddate, - $skip_serialseq, $itemtype, $previousitemtype, $mana_id + $skip_serialseq, $itemtype, $previousitemtype, $mana_id, $auto_claim_enabled ); if ( (C4::Context->preference('Mana') == 1) and ( grep { $_ eq "subscription" } split(/,/, C4::Context->preference('AutoShareWithMana'))) ){ my $result = Koha::SharedContent::send_entity( $query->param('mana_language') || '', $loggedinuser, $subscriptionid, 'subscription'); @@ -463,6 +464,7 @@ sub redirect_mod_subscription { my $itemtype = $query->param('itemtype'); my $previousitemtype = $query->param('previousitemtype'); my $skip_serialseq = $query->param('skip_serialseq'); + my $auto_claim_enabled = $query->param('auto_claim_enabled'); my $mana_id; if ( $query->param('mana_id') ne "" ) { @@ -498,7 +500,7 @@ sub redirect_mod_subscription { $status, $biblionumber, $callnumber, $notes, $letter, $manualhistory, $internalnotes, $serialsadditems, $staffdisplaycount, $opacdisplaycount, $graceperiod, $location, $enddate, $subscriptionid, - $skip_serialseq, $itemtype, $previousitemtype, $mana_id + $skip_serialseq, $itemtype, $previousitemtype, $mana_id, $auto_claim_enabled ); my @additional_fields; -- 2.20.1