Bug 7282 - invalid language selection
[koha.git] / C4 / ItemCirculationAlertPreference.pm
1 package C4::ItemCirculationAlertPreference;
2
3 # This file is part of Koha.
4 #
5 # Koha is free software; you can redistribute it and/or modify it under the
6 # terms of the GNU General Public License as published by the Free Software
7 # Foundation; either version 2 of the License, or (at your option) any later
8 # version.
9 #
10 # Koha is distributed in the hope that it will be useful, but WITHOUT ANY
11 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12 # A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU General Public License along with
15 # Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place,
16 # Suite 330, Boston, MA  02111-1307 USA
17
18 use strict;
19 use warnings;
20 use C4::Context;
21 use C4::Category;
22 use C4::ItemType;
23 use Carp qw(carp croak);
24
25 our $AUTOLOAD;
26
27 # helper function for validating \%opts
28 our $valid = sub {
29     my $opts = shift;
30     for (qw(branchcode categorycode item_type notification)) {
31         exists($opts->{$_}) || croak("'$_' is a required parameter.");
32     }
33 };
34
35
36
37
38 =head1 NAME
39
40 C4::ItemCirculationAlertPreference - manage preferences for sending alerts
41
42 =head1 SYNOPSIS
43
44 Basics:
45
46     use C4::ItemCirculationAlertPreference;
47
48     # a short-cut to reduce typing the long package name over and over again
49     my $preferences = 'C4::ItemCirculationAlertPreference';
50
51 Creating a restriction on sending messages:
52
53     my $pref = $preferences->create({
54         branchcode   => 'CPL',
55         categorycode => 'YA',
56         item_type    => 'BK',
57         notification => 'CHECKOUT',
58     });
59
60 Removing a restriction on sending messages:
61
62     $preferences->delete({
63         branchcode   => 'CPL',
64         categorycode => 'YA',
65         item_type    => 'BK',
66         notification => 'CHECKOUT',
67     });
68
69 =head1 DESCRIPTION
70
71 This class is used to manage the preferences for when an alert may be sent.  By
72 default, item circulation alerts are enabled for every B<branch>, B<patron
73 category> and B<item type>.
74
75 However, if you would like to prevent item circulation alerts from being sent
76 for any combination of these 3 variables, a preference can be inserted into the
77 C<item_circulation_alert_preferences> table to make that a policy.
78
79 =head1 API
80
81 =head2 Class Methods
82
83 =cut
84
85 =head3 C4::ItemCirculationAlertPreference->new(\%opts)
86
87 This is a constructor for an in-memory C4::ItemCirculationAlertPreference
88 object.  The database is not affected by this method.
89
90 =cut
91
92 sub new {
93     my ($class, $opts) = @_;
94     bless $opts => $class;
95 }
96
97
98
99
100 =head3 C4::ItemCirculationAlertPreference->create(\%opts)
101
102 This will find or create an item circulation alert preference.  You must pass
103 it a B<branchcode>, B<categorycode>, B<item_type>, and B<notification>.  Valid
104 values for these attributes are as follows:
105
106 =over 4
107
108 =item branchcode
109
110 branches.branchcode
111
112 =item categorycode
113
114 category.categorycode
115
116 =item item_type
117
118 itemtypes.itemtype
119
120 =item notification
121
122 This can be "CHECKIN" or "CHECKOUT"
123
124 =back
125
126 =cut
127
128 sub create {
129     my ($class, $opts) = @_;
130     $valid->($opts);
131     my $dbh = C4::Context->dbh;
132     my $prefs = $dbh->selectall_arrayref(
133         "SELECT id, branchcode, categorycode, item_type
134         FROM  item_circulation_alert_preferences
135         WHERE branchcode   = ?
136         AND   categorycode = ?
137         AND   item_type    = ?
138         AND   notification = ?",
139         { Slice => {} },
140         $opts->{branchcode},
141         $opts->{categorycode},
142         $opts->{item_type},
143         $opts->{notification},
144     );
145     if (@$prefs) {
146         return $class->new($prefs->[0]);
147     } else {
148         my $success = $dbh->do(
149             "INSERT INTO item_circulation_alert_preferences
150             (branchcode, categorycode, item_type, notification) VALUES (?, ?, ?, ?)",
151             {},
152             $opts->{branchcode},
153             $opts->{categorycode},
154             $opts->{item_type},
155             $opts->{notification},
156         );
157         if ($success) {
158             my $self = {
159                 id           => $dbh->last_insert_id(undef, undef, undef, undef),
160                 branchcode   => $opts->{branchcode},
161                 categorycode => $opts->{categorycode},
162                 item_type    => $opts->{item_type},
163                 notification => $opts->{notification},
164             };
165             return $class->new($self);
166         } else {
167             carp $dbh->errstr;
168             return undef;
169         }
170     }
171 }
172
173
174
175
176 =head3 C4::ItemCirculationAlertPreference->delete(\%opts)
177
178 Delete an item circulation alert preference.  You can delete by either passing
179 in an B<id> or passing in a B<branchcode>, B<categorycode>, B<item_type>
180 triplet.
181
182 =cut
183
184 sub delete {
185     my ($class, $opts) = @_;
186     my $dbh = C4::Context->dbh;
187     if ($opts->{id}) {
188         $dbh->do(
189             "DELETE FROM item_circulation_alert_preferences WHERE id = ?",
190             {},
191             $opts->{id}
192         );
193     } else {
194         $valid->($opts);
195         my $sql =
196             "DELETE FROM item_circulation_alert_preferences
197             WHERE branchcode   = ?
198             AND   categorycode = ?
199             AND   item_type    = ?
200             AND   notification = ?";
201         $dbh->do(
202             $sql,
203             {},
204             $opts->{branchcode},
205             $opts->{categorycode},
206             $opts->{item_type},
207             $opts->{notification},
208         );
209     }
210 }
211
212
213
214
215 =head3 C4::ItemCirculationAlertPreference->is_enabled_for(\%opts)
216
217 Based on the existing preferences in the C<item_circulation_alert_preferences>
218 table, can an alert be sent for the given B<branchcode>, B<categorycode>, and
219 B<itemtype>?
220
221 B<Example>:
222
223     my $alert = 'C4::ItemCirculationAlertPreference';
224     my $conditions = {
225         branchcode   => 'CPL',
226         categorycode => 'IL',
227         item_type    => 'MU',
228     };
229
230     if ($alert->is_enabled_for($conditions)) {
231         # ...
232     }
233
234 =cut
235
236 sub is_disabled_for {
237     my ($class, $opts) = @_;
238     $valid->($opts);
239     my $dbh = C4::Context->dbh;
240
241     # Does a preference exist to block this alert?
242     my $query = qq{
243         SELECT id, branchcode, categorycode, item_type, notification
244           FROM item_circulation_alert_preferences
245          WHERE (branchcode   = ? OR branchcode   = '*')
246            AND (categorycode = ? OR categorycode = '*')
247            AND (item_type    = ? OR item_type    = '*')
248            AND (notification = ? OR notification = '*')
249     };
250
251     my $preferences = $dbh->selectall_arrayref(
252         $query,
253         { Slice => {} },
254         $opts->{branchcode},
255         $opts->{categorycode},
256         $opts->{item_type},
257         $opts->{notification},
258     );
259
260     # If any preferences showed up, we are NOT enabled.
261     return @$preferences;
262 }
263
264 sub is_enabled_for {
265     my ($class, $opts) = @_;
266     return not $class->is_disabled_for($opts);
267 }
268
269
270
271
272 =head3 C4::ItemCirculationAlertPreference->find({ branchcode => $bc, notification => $type })
273
274 This method returns all the item circulation alert preferences for a given
275 branch and notification.
276
277 B<Example>:
278
279     my @branch_prefs = C4::ItemCirculationAlertPreference->find({
280         branchcode   => 'CPL',
281         notification => 'CHECKIN',
282     });
283
284 =cut
285
286 sub find {
287     my ($class, $where) = @_;
288     my $dbh = C4::Context->dbh;
289     my $query = qq{
290         SELECT id, branchcode, categorycode, item_type, notification
291           FROM item_circulation_alert_preferences
292          WHERE branchcode = ? AND notification = ?
293          ORDER BY categorycode, item_type
294     };
295     return    map { $class->new($_) }    @{$dbh->selectall_arrayref(
296         $query,
297         { Slice => {} },
298         $where->{branchcode},
299         $where->{notification},
300     )};
301 }
302
303
304
305
306 =head3 C4::ItemCirculationAlertPreference->grid({ branchcode => $c, notification => $type })
307
308 Return a 2D arrayref for the grid view in F<admin/item_circulation_alert_preferences.pl>.
309 Each row represents a category (like 'Patron' or 'Young Adult') and
310 each column represents an itemtype (like 'Book' or 'Music').
311
312 Each cell contains...
313
314 B<Example>:
315
316     use Data::Dump 'pp';
317     my $grid = C4::ItemCirculationAlertPreference->grid({
318         branchcode   => 'CPL',
319         notification => 'CHECKOUT',
320     });
321     warn pp($grid);
322
323 See F<admin/item_circulation_alerts.pl> to see how this method is used.
324
325 =cut
326
327 sub grid {
328     my ($class, $where) = @_;
329     my @branch_prefs = $class->find($where);
330     my @default_prefs = $class->find({ branchcode => '*', notification => $where->{notification} });
331     my @cc = C4::Category->all;
332     my @it = C4::ItemType->all;
333     my $notification = $where->{notification};
334     my %disabled = map {
335         my $key = $_->categorycode . "-" . $_->item_type . "-" . $notification;
336         $key =~ s/\*/_/g;
337         ($key => 1);
338     } @branch_prefs;
339     my %default = map {
340         my $key = $_->categorycode . "-" . $_->item_type . "-" . $notification;
341         $key =~ s/\*/_/g;
342         ($key => 1);
343     } @default_prefs;
344     my @grid;
345     for my $c (@cc) {
346         my $row = { description => $c->description, items => [] };
347         push @grid, $row;
348         for my $i (@it) {
349             my $key = $c->categorycode . "-" . $i->itemtype . "-" . $notification;
350             $key =~ s/\*/_/g;
351             my @classes;
352             my $text = " ";
353             if ($disabled{$key}) {
354                 push @classes, 'disabled';
355                 $text = "Disabled for $where->{branchcode}";
356             }
357             if ($default{$key}) {
358                 push @classes, 'default';
359                 $text = "Disabled for all";
360             }
361             push @{$row->{items}}, {
362                 class => join(' ', @classes),
363                 id    => $key,
364                 text  => $text,
365             };
366         }
367     }
368     return \@grid;
369 }
370
371
372
373
374 =head2 Object Methods
375
376 These are read-only accessors for the various attributes of a preference.
377
378 =head3 $pref->id
379
380 =cut
381
382 =head3 $pref->branchcode
383
384 =cut
385
386 =head3 $pref->categorycode
387
388 =cut
389
390 =head3 $pref->item_type
391
392 =cut
393
394 =head3 $pref->notification
395
396 =cut
397
398 sub AUTOLOAD {
399     my $self = shift;
400     my $attr = $AUTOLOAD;
401     $attr =~ s/.*://;
402     if (exists $self->{$attr}) {
403         return $self->{$attr};
404     } else {
405         return undef;
406     }
407 }
408
409 sub DESTROY { }
410
411
412
413 =head1 SEE ALSO
414
415 L<C4::Circulation>, F<admin/item_circulation_alerts.pl>
416
417 =head1 AUTHOR
418
419 John Beppu <john.beppu@liblime.com>
420
421 =cut
422
423 1;