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

(-)a/Koha/Notice/Message.pm (+61 lines)
Lines 20-25 use Modern::Perl; Link Here
20
use Carp;
20
use Carp;
21
21
22
use Koha::Database;
22
use Koha::Database;
23
use Koha::Patron::Debarments;
24
use C4::Letters;
23
25
24
use base qw(Koha::Object);
26
use base qw(Koha::Object);
25
27
Lines 33-38 Koha::Notice::Message - Koha notice message Object class, related to the message Link Here
33
35
34
=cut
36
=cut
35
37
38
=head3 restrict_patron_when_notice_fails
39
40
Places a restriction (debarment) on patrons with failed SMS and email notices
41
42
restrict_patron_when_notice_fails($params);
43
44
=cut
45
46
sub restrict_patron_when_notice_fails {
47
    my ($self) = @_;
48
49
    # Set the appropriate restriction (debarment) comment depending if the failed
50
    # message is a SMS or email notice. If the failed notice is neither then
51
    # return without placing a restriction
52
    my $comment;
53
    if ($self->{'message_transport_type'} eq 'email') {
54
        $comment = 'Email address invalid';
55
    } elsif ($self->{'message_transport_type'} eq 'sms') {
56
        $comment = 'SMS number invalid';
57
    } else {
58
        return;
59
    }
60
61
    AddDebarment(
62
        {
63
            borrowernumber => $self->{'borrowernumber'},
64
            type           => 'SUSPENSION',
65
            comment        => $comment,
66
            expiration     => undef,
67
        }
68
    );
69
    return $self;
70
71
}
72
73
=head3 get_failed_notices
74
75
Retrieves all failed notices in the last 7 days and returns (as C4::Letters::_get_unsent_messages does) an array of matching hash
76
referenced rows from message_queue with some borrower information added
77
78
my $failed_notices = get_failed_notices();
79
80
=cut
81
82
sub get_failed_notices {
83
    my $dbh = C4::Context->dbh();
84
85
    my $statement = qq{
86
        SELECT mq.message_id, mq.borrowernumber, mq.subject, mq.content, mq.message_transport_type, mq.status, mq.time_queued, mq.from_address, mq.to_address, mq.content_type, b.branchcode, mq.letter_code
87
        FROM message_queue mq
88
        LEFT JOIN borrowers b ON b.borrowernumber = mq.borrowernumber
89
        WHERE status = ?
90
        AND mq.time_queued BETWEEN date_sub(now(),INTERVAL 1 WEEK) and now();
91
    };
92
    my $sth = $dbh->prepare($statement);
93
    my $result = $sth->execute('failed');
94
    return $sth->fetchall_arrayref({});
95
}
96
36
=head3 type
97
=head3 type
37
98
38
=cut
99
=cut
(-)a/installer/data/mysql/atomicupdate/bug_23295-add_RestrictPatronsWithFailedNotices_syspref.sql (+1 lines)
Line 0 Link Here
1
INSERT IGNORE INTO systempreferences (variable, value, options, explanation, type) VALUES ('RestrictPatronsWithFailedNotices', 0, "Do|Don't", 'If enabled then when SMS and email notices fail sending at the Koha level then a debarment will be applied to a patrons account', 'YesNo');
(-)a/installer/data/mysql/sysprefs.sql (+1 lines)
Lines 535-540 INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` Link Here
535
('RESTdefaultPageSize','20','','Default page size for endpoints listing objects','Integer'),
535
('RESTdefaultPageSize','20','','Default page size for endpoints listing objects','Integer'),
536
('RESTOAuth2ClientCredentials','0',NULL,'If enabled, the OAuth2 client credentials flow is enabled for the REST API.','YesNo'),
536
('RESTOAuth2ClientCredentials','0',NULL,'If enabled, the OAuth2 client credentials flow is enabled for the REST API.','YesNo'),
537
('RESTPublicAPI','1',NULL,'If enabled, the REST API will expose the /public endpoints.','YesNo'),
537
('RESTPublicAPI','1',NULL,'If enabled, the REST API will expose the /public endpoints.','YesNo'),
538
('RestrictPatronsWithFailedNotices', 0, "Do|Don't", 'If enabled then when SMS and email notices fail sending at the Koha level then a debarment will be applied to a patrons account', 'YesNo'),
538
('RestrictedPageLocalIPs','',NULL,'Beginning of IP addresses considered as local (comma separated ex: "127.0.0,127.0.2")','Free'),
539
('RestrictedPageLocalIPs','',NULL,'Beginning of IP addresses considered as local (comma separated ex: "127.0.0,127.0.2")','Free'),
539
('RestrictedPageContent','',NULL,'HTML content of the restricted page','TextArea'),
540
('RestrictedPageContent','',NULL,'HTML content of the restricted page','TextArea'),
540
('RestrictedPageTitle','',NULL,'Title of the restricted page (breadcrumb and header)','Free'),
541
('RestrictedPageTitle','',NULL,'Title of the restricted page (breadcrumb and header)','Free'),
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/patrons.pref (+7 lines)
Lines 257-262 Patrons: Link Here
257
               yes: Allow patrons
257
               yes: Allow patrons
258
               no: Allow only staff
258
               no: Allow only staff
259
         - "to allow/disallow auto renewal for account. If allowed a patron will be able to update their own account to allow/disallow auto renewals"
259
         - "to allow/disallow auto renewal for account. If allowed a patron will be able to update their own account to allow/disallow auto renewals"
260
    -
261
         - pref: RestrictPatronsWithFailedNotices
262
           choices:
263
               yes: Do
264
               no: "Don't"
265
         - "apply a restriction to a patron when their email and SMS messages fail sending at the Koha level."
266
         - "<br><strong>NOTE:</strong> This system preference requires the <code>misc/cronjobs/restrict_patrons_with_failed_notices.pl</code> cronjob. Ask your system administrator to schedule it."
260
267
261
    Privacy:
268
    Privacy:
262
     -
269
     -
(-)a/misc/cronjobs/restrict_patrons_with_failed_notices.pl (+137 lines)
Line 0 Link Here
1
#!/usr/bin/perl
2
3
use Modern::Perl;
4
5
use Getopt::Long;
6
use Pod::Usage;
7
use C4::Log;
8
9
use C4::Context;
10
use Koha::Patron::Debarments;
11
use Koha::Patrons;
12
use C4::Letters;
13
use Koha::Notice::Message;
14
15
# Getting options
16
my ($help, $verbose, $confirm, $type);
17
GetOptions(
18
    'h|help'    => \$help,
19
    'v|verbose' => \$verbose,
20
    'c|confirm' => \$confirm,
21
);
22
23
pod2usage(1) if $help;
24
$verbose = 1 unless $confirm;
25
26
if ( ! C4::Context->preference('RestrictPatronsWithFailedNotices') ) {
27
    warn <<'END_WARN';
28
29
The 'RestrictPatronsWithFailedNotices' syspref is off.
30
Therefore, it is unlikely that this script will actually place any restrictions
31
on patrons with failed SMS or email notices.
32
To change this, enable the 'RestrictPatronsWithFailedNotices' syspref.
33
34
END_WARN
35
}
36
cronlogaction();
37
38
my $failed_notices = Koha::Notice::Message::get_failed_notices();
39
40
if ( C4::Context->preference('RestrictPatronsWithFailedNotices') ) {
41
   if ( @$failed_notices ) {
42
        say "There are borrowers with failed SMS or email notices";
43
44
        foreach my $failed_notice ( @$failed_notices ) {
45
46
            # If failed notice is not a sms or email notice then skip to next failed notice
47
            next unless ($failed_notice->{message_transport_type} eq 'sms' || $failed_notice->{message_transport_type} eq 'email');
48
49
            # If failed sms or email notice has no recipient patron then skip to next failed
50
            # notice
51
            next unless $failed_notice->{borrowernumber};
52
53
            # Find the patron recipient of the failed SMS or email notice.
54
            my $patron  = Koha::Patrons->find( $failed_notice->{borrowernumber} );
55
56
            # Check if patron of failed SMS or email notice is already restricted due to having
57
            # this happen before. If they are already restricted due to having invalid SMS or
58
            # email address don't apply a new restriction (debarment) to their account.
59
            if ( @{ Koha::Patron::Debarments::GetDebarments({ borrowernumber => $patron->borrowernumber, comment  => 'SMS number invalid' }) } ) {
60
                say "Patron " . $patron->borrowernumber . ":" . " " . $patron->firstname . " " . $patron->surname . " " . "is currently restricted due to having an invalid SMS number. No new restriction applied";
61
                next;
62
            } elsif ( @{ Koha::Patron::Debarments::GetDebarments({ borrowernumber => $patron->borrowernumber, comment  => 'Email address invalid' }) }) {
63
                say "Patron " . $patron->borrowernumber . ":" . " " . $patron->firstname . " " . $patron->surname . " " . "is currently restricted due to having an invalid email address. No new restriction applied";
64
                next;
65
            }
66
            if ($confirm) {
67
                # Patron has not been previously restricted for having failed SMS
68
                # or email addresses apply a restriction now.
69
                say "Applying restriction to patron " . $patron->borrowernumber . ":" . " " . $patron->firstname . " " . $patron->surname;
70
                Koha::Notice::Message::restrict_patron_when_notice_fails($failed_notice);
71
            }
72
        }
73
   } else {
74
        say "There are no failed SMS or email notices";
75
   }
76
}
77
78
exit(0);
79
80
__END__
81
82
=head1 NAME
83
84
restrict_patrons_with_failed_notices.pl
85
86
=head1 SYNOPSIS
87
88
./restrict_patrons_with_failed_notices.pl -h
89
90
Use this script to creates a debarment for all patrons with failed SMS and email notices.
91
92
The 'RestrictPatronsWithFailedNotices' syspref must be enabled for this script to place restrictions to patrons accounts.
93
94
=head1 OPTIONS
95
96
=over 8
97
98
=item B<-h|--help>
99
100
Prints this help message
101
102
=item B<-v|--verbose>
103
104
Set the verbose flag
105
106
=item B<-c|--confirm>
107
108
The script will alter the database placing a restriction on patrons with failed SMS and email notices.
109
110
=back
111
112
=head1 AUTHOR
113
114
Alex Buckley <alexbuckley@catalyst.net.nz>
115
116
=head1 COPYRIGHT
117
118
Copyright 2019 Catalyst IT
119
120
=head1 LICENSE
121
122
This file is part of Koha.
123
124
Koha is free software; you can redistribute it and/or modify it
125
under the terms of the GNU General Public License as published by
126
the Free Software Foundation; either version 3 of the License, or
127
(at your option) any later version.
128
129
Koha is distributed in the hope that it will be useful, but
130
WITHOUT ANY WARRANTY; without even the implied warranty of
131
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
132
GNU General Public License for more details.
133
134
You should have received a copy of the GNU General Public License
135
along with Koha; if not, see <http://www.gnu.org/licenses>.
136
137
=cut
(-)a/t/db_dependent/Koha/Notices.t (-2 / +84 lines)
Lines 19-25 Link Here
19
19
20
use Modern::Perl;
20
use Modern::Perl;
21
21
22
use Test::More tests => 3;
22
use Test::More tests => 8;
23
23
24
use Koha::Notice::Templates;
24
use Koha::Notice::Templates;
25
use Koha::Database;
25
use Koha::Database;
Lines 66-70 $retrieved_template->delete; Link Here
66
is( Koha::Notice::Templates->search->count,
66
is( Koha::Notice::Templates->search->count,
67
    $nb_of_templates, 'Delete should have deleted the template' );
67
    $nb_of_templates, 'Delete should have deleted the template' );
68
68
69
# Test bug 23295 - Test the new subroutine Koha::Notice::Message::get_failed_notices()
70
my $dbh = C4::Context->dbh;
71
72
# Remove all existing messages in the message_queue
73
$dbh->do(q|DELETE FROM message_queue|);
74
75
# Make a patron
76
my $patron_category = $builder->build({ source => 'Category' })->{categorycode};
77
my $borrowernumber = Koha::Patron->new({
78
   firstname    => 'Jane',
79
   surname      => 'Smith',
80
   categorycode => $patron_category,
81
   branchcode   => $library->{branchcode},
82
   smsalertnumber => undef,
83
})->store->borrowernumber;
84
85
# With all notices removed from the message_queue table confirm get_failed_notices() returns 0
86
my $failed_notices = Koha::Notice::Message::get_failed_notices();
87
is( scalar @$failed_notices, 0, 'No failed notices currently exist');
88
89
# Add a failed notice to the message_queue table
90
$dbh->do(q|
91
    INSERT INTO message_queue(borrowernumber, subject, content, message_transport_type, status, letter_code)
92
    VALUES (?, 'subject', 'content', 'sms', 'failed', 'just_a_code')
93
    |, undef, $borrowernumber
94
);
95
96
# With one failed notice in the message_queue table confirm get_failed_notices() returns 1
97
my $failed_notices2 = Koha::Notice::Message::get_failed_notices();
98
is( scalar(@$failed_notices2), 1, 'One failed notice currently exists');
99
100
# Change failed notice status to 'pending'
101
$dbh->do(q|UPDATE message_queue SET status='pending'|);
102
103
# With the 1 failed notice in the message_queue table marked 'pending' confirm get_failed_notices() returns 0
104
my $failed_notices3 = Koha::Notice::Message::get_failed_notices();
105
is( scalar(@$failed_notices3), 0, 'No failed notices currently existing, now the notice has been marked pending');
106
107
108
# Test bug 23295 - Test the new subroutine Koha::Notice::Message::restrict_patron_when_notice_fails()
109
110
# Empty the borrower_debarments table
111
$dbh->do(q|DELETE FROM borrower_debarments|);
112
113
# Change the status of the notice back to 'failed'
114
$dbh->do(q|UPDATE message_queue SET status='failed'|);
115
116
my $failed_notices4 = Koha::Notice::Message::get_failed_notices();
117
118
# There should be one failed notice
119
if (@$failed_notices4) {
120
    # Restrict the borrower who has the failed notice
121
    foreach my $failed_notice (@$failed_notices4) {
122
        if ($failed_notice->{message_transport_type} eq 'sms' || $failed_notice->{message_transport_type} eq 'email') {
123
            Koha::Notice::Message::restrict_patron_when_notice_fails($failed_notice);
124
        }
125
    }
126
}
127
128
# Confirm that the restrict_patron_when_notice_fails() has added a restriction to the patron
129
is(@{ Koha::Patron::Debarments::GetDebarments({ borrowernumber => $borrowernumber, comment  => 'SMS number invalid' })}, 1, "Patron has a restriction placed on them");
130
131
# Restrict the borrower who has the failed notice
132
foreach my $failed_notice (@$failed_notices4) {
133
    if ($failed_notice->{message_transport_type} eq 'sms' || $failed_notice->{message_transport_type} eq 'email') {
134
135
        # If the borrower already has a debarment for failed SMS or email notice then don't apply
136
        # a new debarment to their account
137
        if ( @{ Koha::Patron::Debarments::GetDebarments({ borrowernumber => $borrowernumber, comment  => 'SMS number invalid' }) } ) {
138
            next;
139
        } elsif ( @{ Koha::Patron::Debarments::GetDebarments({ borrowernumber => $borrowernumber, comment  => 'Email address invalid' }) }) {
140
            next;
141
        }
142
143
        # Place the debarment if the borrower doesn't already have one for failed SMS or email
144
        # notice
145
        Koha::Notice::Message::restrict_patron_when_notice_fails($failed_notice);
146
    }
147
}
148
149
# Confirm that no new debarment is added to the borrower
150
is(@{ Koha::Patron::Debarments::GetDebarments({ borrowernumber => $borrowernumber, comment  => 'SMS number invalid' })}, 1, "No new restriction has been placed on the patron");
151
69
$schema->storage->txn_rollback;
152
$schema->storage->txn_rollback;
70
153
71
- 

Return to bug 23295