Bug 24412: (follow-up) prevent request.pl from failing
[koha.git] / C4 / ItemCirculationAlertPreference.pm
blob4eb263c19629505ee7d6ab65d2d57253d06dd4da
1 package C4::ItemCirculationAlertPreference;
3 # Copyright Liblime 2009
5 # This file is part of Koha.
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.
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.
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>.
20 use strict;
21 use warnings;
22 use C4::Context;
23 use Carp qw(carp croak);
25 use Koha::ItemTypes;
26 use Koha::Patron::Categories;
28 our $AUTOLOAD;
30 # helper function for validating \%opts
31 our $valid = sub {
32 my $opts = shift;
33 for (qw(branchcode categorycode item_type notification)) {
34 exists($opts->{$_}) || croak("'$_' is a required parameter.");
41 =head1 NAME
43 C4::ItemCirculationAlertPreference - manage preferences for sending alerts
45 =head1 SYNOPSIS
47 Basics:
49 use C4::ItemCirculationAlertPreference;
51 # a short-cut to reduce typing the long package name over and over again
52 my $preferences = 'C4::ItemCirculationAlertPreference';
54 Creating a restriction on sending messages:
56 my $pref = $preferences->create({
57 branchcode => 'CPL',
58 categorycode => 'YA',
59 item_type => 'BK',
60 notification => 'CHECKOUT',
61 });
63 Removing a restriction on sending messages:
65 $preferences->delete({
66 branchcode => 'CPL',
67 categorycode => 'YA',
68 item_type => 'BK',
69 notification => 'CHECKOUT',
70 });
72 =head1 DESCRIPTION
74 This class is used to manage the preferences for when an alert may be sent. By
75 default, item circulation alerts are enabled for every B<branch>, B<patron
76 category> and B<item type>.
78 However, if you would like to prevent item circulation alerts from being sent
79 for any combination of these 3 variables, a preference can be inserted into the
80 C<item_circulation_alert_preferences> table to make that a policy.
82 =head1 API
84 =head2 Class Methods
86 =cut
88 =head3 C4::ItemCirculationAlertPreference->new(\%opts)
90 This is a constructor for an in-memory C4::ItemCirculationAlertPreference
91 object. The database is not affected by this method.
93 =cut
95 sub new {
96 my ($class, $opts) = @_;
97 bless $opts => $class;
103 =head3 C4::ItemCirculationAlertPreference->create(\%opts)
105 This will find or create an item circulation alert preference. You must pass
106 it a B<branchcode>, B<categorycode>, B<item_type>, and B<notification>. Valid
107 values for these attributes are as follows:
109 =over 4
111 =item branchcode
113 branches.branchcode
115 =item categorycode
117 category.categorycode
119 =item item_type
121 itemtypes.itemtype
123 =item notification
125 This can be "CHECKIN" or "CHECKOUT"
127 =back
129 =cut
131 sub create {
132 my ($class, $opts) = @_;
133 $valid->($opts);
134 my $dbh = C4::Context->dbh;
135 my $prefs = $dbh->selectall_arrayref(
136 "SELECT id, branchcode, categorycode, item_type
137 FROM item_circulation_alert_preferences
138 WHERE branchcode = ?
139 AND categorycode = ?
140 AND item_type = ?
141 AND notification = ?",
142 { Slice => {} },
143 $opts->{branchcode},
144 $opts->{categorycode},
145 $opts->{item_type},
146 $opts->{notification},
148 if (@$prefs) {
149 return $class->new($prefs->[0]);
150 } else {
151 my $success = $dbh->do(
152 "INSERT INTO item_circulation_alert_preferences
153 (branchcode, categorycode, item_type, notification) VALUES (?, ?, ?, ?)",
155 $opts->{branchcode},
156 $opts->{categorycode},
157 $opts->{item_type},
158 $opts->{notification},
160 if ($success) {
161 my $self = {
162 id => $dbh->last_insert_id(undef, undef, undef, undef),
163 branchcode => $opts->{branchcode},
164 categorycode => $opts->{categorycode},
165 item_type => $opts->{item_type},
166 notification => $opts->{notification},
168 return $class->new($self);
169 } else {
170 carp $dbh->errstr;
171 return;
179 =head3 C4::ItemCirculationAlertPreference->delete(\%opts)
181 Delete an item circulation alert preference. You can delete by either passing
182 in an B<id> or passing in a B<branchcode>, B<categorycode>, B<item_type>
183 triplet.
185 =cut
187 sub delete {
188 my ($class, $opts) = @_;
189 my $dbh = C4::Context->dbh;
190 if ($opts->{id}) {
191 $dbh->do(
192 "DELETE FROM item_circulation_alert_preferences WHERE id = ?",
194 $opts->{id}
196 } else {
197 $valid->($opts);
198 my $sql =
199 "DELETE FROM item_circulation_alert_preferences
200 WHERE branchcode = ?
201 AND categorycode = ?
202 AND item_type = ?
203 AND notification = ?";
204 $dbh->do(
205 $sql,
207 $opts->{branchcode},
208 $opts->{categorycode},
209 $opts->{item_type},
210 $opts->{notification},
218 =head3 C4::ItemCirculationAlertPreference->is_enabled_for(\%opts)
220 Based on the existing preferences in the C<item_circulation_alert_preferences>
221 table, can an alert be sent for the given B<branchcode>, B<categorycode>, and
222 B<itemtype>?
224 B<Example>:
226 my $alert = 'C4::ItemCirculationAlertPreference';
227 my $conditions = {
228 branchcode => 'CPL',
229 categorycode => 'IL',
230 item_type => 'MU',
233 if ($alert->is_enabled_for($conditions)) {
234 # ...
237 =cut
239 sub is_disabled_for {
240 my ($class, $opts) = @_;
241 $valid->($opts);
242 my $dbh = C4::Context->dbh;
244 # Does a preference exist to block this alert?
245 my $query = qq{
246 SELECT id, branchcode, categorycode, item_type, notification
247 FROM item_circulation_alert_preferences
248 WHERE (branchcode = ? OR branchcode = '*')
249 AND (categorycode = ? OR categorycode = '*')
250 AND (item_type = ? OR item_type = '*')
251 AND (notification = ? OR notification = '*')
254 my $preferences = $dbh->selectall_arrayref(
255 $query,
256 { Slice => {} },
257 $opts->{branchcode},
258 $opts->{categorycode},
259 $opts->{item_type},
260 $opts->{notification},
263 # If any preferences showed up, we are NOT enabled.
264 return @$preferences;
267 sub is_enabled_for {
268 my ($class, $opts) = @_;
269 return not $class->is_disabled_for($opts);
275 =head3 C4::ItemCirculationAlertPreference->find({ branchcode => $bc, notification => $type })
277 This method returns all the item circulation alert preferences for a given
278 branch and notification.
280 B<Example>:
282 my @branch_prefs = C4::ItemCirculationAlertPreference->find({
283 branchcode => 'CPL',
284 notification => 'CHECKIN',
287 =cut
289 sub find {
290 my ($class, $where) = @_;
291 my $dbh = C4::Context->dbh;
292 my $query = qq{
293 SELECT id, branchcode, categorycode, item_type, notification
294 FROM item_circulation_alert_preferences
295 WHERE branchcode = ? AND notification = ?
296 ORDER BY categorycode, item_type
298 return map { $class->new($_) } @{$dbh->selectall_arrayref(
299 $query,
300 { Slice => {} },
301 $where->{branchcode},
302 $where->{notification},
309 =head3 C4::ItemCirculationAlertPreference->grid({ branchcode => $c, notification => $type })
311 Return a 2D arrayref for the grid view in F<admin/item_circulation_alert_preferences.pl>.
312 Each row represents a category (like 'Patron' or 'Young Adult') and
313 each column represents an itemtype (like 'Book' or 'Music').
315 Each cell contains...
317 B<Example>:
319 use Data::Dump 'pp';
320 my $grid = C4::ItemCirculationAlertPreference->grid({
321 branchcode => 'CPL',
322 notification => 'CHECKOUT',
324 warn pp($grid);
326 See F<admin/item_circulation_alerts.pl> to see how this method is used.
328 =cut
330 sub grid {
331 my ($class, $where) = @_;
332 my @branch_prefs = $class->find($where);
333 my @default_prefs = $class->find({ branchcode => '*', notification => $where->{notification} });
334 my @cc = Koha::Patron::Categories->search_limited;
335 my @it = Koha::ItemTypes->search;
336 my $notification = $where->{notification};
337 my %disabled = map {
338 my $key = $_->categorycode . "-" . $_->item_type . "-" . $notification;
339 $key =~ s/\*/_/g;
340 ($key => 1);
341 } @branch_prefs;
342 my %default = map {
343 my $key = $_->categorycode . "-" . $_->item_type . "-" . $notification;
344 $key =~ s/\*/_/g;
345 ($key => 1);
346 } @default_prefs;
347 my @grid;
348 for my $c (@cc) {
349 my $row = { description => $c->description, items => [] };
350 push @grid, $row;
351 for my $i (@it) {
352 my $key = $c->categorycode . "-" . $i->itemtype . "-" . $notification;
353 $key =~ s/\*/_/g;
354 my @classes;
355 my $text = " ";
356 if ($disabled{$key}) {
357 push @classes, 'disabled';
358 $text = "Disabled for $where->{branchcode}";
360 if ($default{$key}) {
361 push @classes, 'default';
362 $text = "Disabled for all";
364 push @{$row->{items}}, {
365 class => join(' ', @classes),
366 id => $key,
367 text => $text,
371 return \@grid;
377 =head2 Object Methods
379 These are read-only accessors for the various attributes of a preference.
381 =head3 $pref->id
383 =cut
385 =head3 $pref->branchcode
387 =cut
389 =head3 $pref->categorycode
391 =cut
393 =head3 $pref->item_type
395 =cut
397 =head3 $pref->notification
399 =cut
401 sub AUTOLOAD {
402 my $self = shift;
403 my $attr = $AUTOLOAD;
404 $attr =~ s/.*://;
405 if (exists $self->{$attr}) {
406 return $self->{$attr};
407 } else {
408 return;
412 sub DESTROY { }
416 =head1 SEE ALSO
418 L<C4::Circulation>, F<admin/item_circulation_alerts.pl>
420 =head1 AUTHOR
422 John Beppu <john.beppu@liblime.com>
424 =cut