Bug 16011: $VERSION - Remove the $VERSION init
[koha.git] / C4 / Members / Messaging.pm
blob3b1c14bec351fb6af1799f520a8ceb0254212258
1 package C4::Members::Messaging;
3 # Copyright (C) 2008 LibLime
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;
24 use vars qw();
26 BEGIN {
27 # set the version for version checking
30 =head1 NAME
32 C4::Members::Messaging - manage patron messaging preferences
34 =head1 SYNOPSIS
36 use C4::Members::Messaging
38 =head1 DESCRIPTION
40 This module lets you modify a patron's messaging preferences.
42 =head1 FUNCTIONS
44 =head2 GetMessagingPreferences
46 my $preferences = C4::Members::Messaging::GetMessagingPreferences( { borrowernumber => $borrower->{'borrowernumber'},
47 message_name => 'DUE' } );
49 my $preferences = C4::Members::Messaging::GetMessagingPreferences( { categorycode => 'LIBRARY',
50 message_name => 'DUE' } );
52 returns: a hashref of messaging preferences for a borrower or patron category for a particlar message_name
54 Requires either a borrowernumber or a categorycode key, but not both.
56 =cut
58 sub GetMessagingPreferences {
59 my $params = shift;
61 return unless exists $params->{message_name};
62 return unless exists $params->{borrowernumber} xor exists $params->{categorycode}; # yes, xor
63 my $sql = <<'END_SQL';
64 SELECT borrower_message_preferences.*,
65 borrower_message_transport_preferences.message_transport_type,
66 message_attributes.message_name,
67 message_attributes.takes_days,
68 message_transports.is_digest,
69 message_transports.letter_module,
70 message_transports.letter_code
71 FROM borrower_message_preferences
72 LEFT JOIN borrower_message_transport_preferences
73 ON borrower_message_transport_preferences.borrower_message_preference_id = borrower_message_preferences.borrower_message_preference_id
74 LEFT JOIN message_attributes
75 ON message_attributes.message_attribute_id = borrower_message_preferences.message_attribute_id
76 LEFT JOIN message_transports
77 ON message_transports.message_attribute_id = message_attributes.message_attribute_id
78 AND message_transports.message_transport_type = borrower_message_transport_preferences.message_transport_type
79 WHERE message_attributes.message_name = ?
80 END_SQL
82 my @bind_params = ( $params->{'message_name'} );
83 if ( exists $params->{'borrowernumber'} ) {
84 $sql .= " AND borrower_message_preferences.borrowernumber = ? ";
85 push @bind_params, $params->{borrowernumber};
86 } else {
87 $sql .= " AND borrower_message_preferences.categorycode = ? ";
88 push @bind_params, $params->{categorycode};
91 my $sth = C4::Context->dbh->prepare($sql);
92 $sth->execute(@bind_params);
93 my $return;
94 my %transports; # helps build a list of unique message_transport_types
95 ROW: while ( my $row = $sth->fetchrow_hashref() ) {
96 next ROW unless $row->{'message_attribute_id'};
97 $return->{'days_in_advance'} = $row->{'days_in_advance'} if defined $row->{'days_in_advance'};
98 $return->{'wants_digest'} = $row->{'wants_digest'} if defined $row->{'wants_digest'};
99 $return->{'letter_code'} = $row->{'letter_code'};
100 next unless defined $row->{'message_transport_type'};
101 $return->{'transports'}->{ $row->{'message_transport_type'} } = $row->{'letter_code'};
103 return $return;
106 =head2 SetMessagingPreference
108 This method defines how a user (or a default for a patron category) wants to get a certain
109 message delivered. The list of valid message types can be delivered can be found in the
110 C<message_attributes> table, and the list of valid message transports can be
111 found in the C<message_transport_types> table.
113 C4::Members::Messaging::SetMessagingPreference( { borrowernumber => $borrower->{'borrowernumber'}
114 message_attribute_id => $message_attribute_id,
115 message_transport_types => [ qw( email sms ) ],
116 days_in_advance => 5
117 wants_digest => 1 } )
119 returns nothing useful.
121 =cut
123 sub SetMessagingPreference {
124 my $params = shift;
126 unless (exists $params->{borrowernumber} xor exists $params->{categorycode}) { # yes, xor
127 warn "SetMessagingPreference called without exactly one of borrowernumber or categorycode";
128 return;
130 foreach my $required ( qw( message_attribute_id message_transport_types ) ) {
131 if ( ! exists $params->{ $required } ) {
132 warn "SetMessagingPreference called without required parameter: $required";
133 return;
136 $params->{'days_in_advance'} = undef unless exists ( $params->{'days_in_advance'} );
137 $params->{'wants_digest'} = 0 unless exists ( $params->{'wants_digest'} );
139 my $dbh = C4::Context->dbh();
141 my $delete_sql = <<'END_SQL';
142 DELETE FROM borrower_message_preferences
143 WHERE message_attribute_id = ?
144 END_SQL
145 my @bind_params = ( $params->{'message_attribute_id'} );
146 if ( exists $params->{'borrowernumber'} ) {
147 $delete_sql .= " AND borrowernumber = ? ";
148 push @bind_params, $params->{borrowernumber};
149 } else {
150 $delete_sql .= " AND categorycode = ? ";
151 push @bind_params, $params->{categorycode};
153 my $sth = $dbh->prepare( $delete_sql );
154 my $deleted = $sth->execute( @bind_params );
156 if ( $params->{'message_transport_types'} ) {
157 my $insert_bmp = <<'END_SQL';
158 INSERT INTO borrower_message_preferences
159 (borrower_message_preference_id, borrowernumber, categorycode, message_attribute_id, days_in_advance, wants_digest)
160 VALUES
161 (NULL, ?, ?, ?, ?, ?)
162 END_SQL
164 $sth = C4::Context->dbh()->prepare($insert_bmp);
165 # set up so that we can easily construct the insert SQL
166 $params->{'borrowernumber'} = undef unless exists ( $params->{'borrowernumber'} );
167 $params->{'categorycode'} = undef unless exists ( $params->{'categorycode'} );
168 my $success = $sth->execute( $params->{'borrowernumber'},
169 $params->{'categorycode'},
170 $params->{'message_attribute_id'},
171 $params->{'days_in_advance'},
172 $params->{'wants_digest'} );
173 # my $borrower_message_preference_id = $dbh->last_insert_id();
174 my $borrower_message_preference_id = $dbh->{'mysql_insertid'};
176 my $insert_bmtp = <<'END_SQL';
177 INSERT INTO borrower_message_transport_preferences
178 (borrower_message_preference_id, message_transport_type)
179 VALUES
180 (?, ?)
181 END_SQL
182 $sth = C4::Context->dbh()->prepare($insert_bmtp);
183 foreach my $transport ( @{$params->{'message_transport_types'}}) {
184 my $success = $sth->execute( $borrower_message_preference_id, $transport );
187 return;
190 =head2 GetMessagingOptions
192 my $messaging_options = C4::Members::Messaging::GetMessagingOptions()
194 returns a hashref of messaging options available.
196 =cut
198 sub GetMessagingOptions {
200 my $sql = <<'END_SQL';
201 select message_attributes.message_attribute_id, takes_days, message_name, message_transport_type, is_digest
202 FROM message_attributes
203 LEFT JOIN message_transports
204 ON message_attributes.message_attribute_id = message_transports.message_attribute_id
205 END_SQL
207 my $sth = C4::Context->dbh->prepare($sql);
208 $sth->execute();
209 my $choices;
210 while ( my $row = $sth->fetchrow_hashref() ) {
211 $choices->{ $row->{'message_name'} }->{'message_attribute_id'} = $row->{'message_attribute_id'};
212 $choices->{ $row->{'message_name'} }->{'message_name'} = $row->{'message_name'};
213 $choices->{ $row->{'message_name'} }->{'takes_days'} = $row->{'takes_days'};
214 $choices->{ $row->{'message_name'} }->{'has_digest'} = 1 if $row->{'is_digest'};
215 $choices->{ $row->{'message_name'} }->{'transport_' . $row->{'message_transport_type'}} = ' ';
218 my @return = values %$choices;
220 @return = sort { $a->{message_attribute_id} <=> $b->{message_attribute_id} } @return;
222 # warn( Data::Dumper->Dump( [ \@return ], [ 'return' ] ) );
223 return \@return;
226 =head2 SetMessagingPreferencesFromDefaults
228 C4::Members::Messaging::SetMessagingPreferencesFromDefaults( { borrowernumber => $borrower->{'borrowernumber'}
229 categorycode => 'CPL' } );
231 Given a borrowernumber and a patron category code (from the C<borrowernumber> and C<categorycode> keys
232 in the parameter hashref), replace all of the patron's current messaging preferences with
233 whatever defaults are defined for the patron category.
235 =cut
237 sub SetMessagingPreferencesFromDefaults {
238 my $params = shift;
240 foreach my $required ( qw( borrowernumber categorycode ) ) {
241 unless ( exists $params->{ $required } ) {
242 die "SetMessagingPreferencesFromDefaults called without required parameter: $required";
246 my $messaging_options = GetMessagingOptions();
247 OPTION: foreach my $option ( @$messaging_options ) {
248 my $default_pref = GetMessagingPreferences( { categorycode => $params->{categorycode},
249 message_name => $option->{'message_name'} } );
250 # FIXME - except for setting the borrowernumber, it really ought to be possible
251 # to have the output of GetMessagingPreferences be able to be the input
252 # to SetMessagingPreference
253 my @message_transport_types = keys %{ $default_pref->{transports} };
254 $default_pref->{message_attribute_id} = $option->{'message_attribute_id'};
255 $default_pref->{message_transport_types} = \@message_transport_types;
256 $default_pref->{borrowernumber} = $params->{borrowernumber};
257 SetMessagingPreference( $default_pref );
261 =head1 TABLES
263 =head2 message_queue
265 The actual messages which will be sent via a cron job running
266 F<misc/cronjobs/process_message_queue.pl>.
268 =head2 message_attributes
270 What kinds of messages can be sent?
272 =head2 message_transport_types
274 What transports can messages be sent vith? (email, sms, etc.)
276 =head2 message_transports
278 How are message_attributes and message_transport_types correlated?
280 =head2 borrower_message_preferences
282 What messages do the borrowers want to receive?
284 =head2 borrower_message_transport_preferences
286 What transport should a message be sent with?
288 =head1 CONFIG
290 =head2 Adding a New Kind of Message to the System
292 =over 4
294 =item 1.
296 Add a new template to the `letter` table.
298 =item 2.
300 Insert a row into the `message_attributes` table.
302 =item 3.
304 Insert rows into `message_transports` for each message_transport_type.
306 =back
308 =head1 SEE ALSO
310 L<C4::Letters>
312 =head1 AUTHOR
314 Koha Development Team <http://koha-community.org/>
316 Andrew Moore <andrew.moore@liblime.com>
318 =cut