]> wagnertech.de Git - mfinanz.git/blob - SL/BackgroundJob/SendFollowUpReminder.pm
date error in mapping
[mfinanz.git] / SL / BackgroundJob / SendFollowUpReminder.pm
1 package SL::BackgroundJob::SendFollowUpReminder;
2
3 use strict;
4
5 use parent qw(SL::BackgroundJob::Base);
6
7 use SL::DB::AuthUser;
8 use SL::DB::FollowUp;
9 use SL::Locale::String qw(t8);
10 use SL::Mailer;
11 use SL::Presenter;
12 use SL::Util qw(trim);
13
14 use DateTime;
15 use File::Slurp qw(slurp);
16 use List::Util qw(any);
17 use Try::Tiny;
18 use URI;
19
20 sub create_job {
21   $_[0]->create_standard_job('7 6 1-5 * *'); # every workday at 06:07
22 }
23
24 use Rose::Object::MakeMethods::Generic (
25  'scalar' => [ qw(params) ],
26 );
27
28 #
29 # If job does not throw an error,
30 # success in background_job_histories is 'success'.
31 # It is 'failure' otherwise.
32 #
33 # Return value goes to result in background_job_histories.
34 #
35 sub run {
36   my ($self, $db_obj) = @_;
37
38   $self->{$_} = [] for qw(job_errors);
39
40   $self->initialize_params($db_obj->data_as_hash) if $db_obj;
41
42   my   @follow_up_date_where = ();
43   push @follow_up_date_where, (follow_up_date => { ge    => [ $self->params->{from_date} ]}) if $self->params->{from_date};
44   push @follow_up_date_where, (follow_up_date => { le    => [ $self->params->{to_date}   ]}) if $self->params->{to_date};
45
46   my $follow_ups = SL::DB::Manager::FollowUp->get_all(where        => ['done.id' => undef,
47                                                                        @follow_up_date_where, ],
48                                                       with_objects => ['done'],
49                                                       sort_by      => ['follow_up_date']);
50
51   # Collect follow ups for users with e-mail-address.
52   my $mail_to_by_employee_id;
53   foreach my $follow_up (@$follow_ups) {
54
55     # add link
56     $follow_up->{link} = URI->new_abs('fu.pl?action=edit&id=' . $follow_up->id, $::form->_get_request_uri);
57
58     foreach my $employee (@{ $follow_up->created_for_employees }) {
59       next if $employee->deleted;
60
61       if (!exists $mail_to_by_employee_id->{$employee->id}) {
62         my $user = SL::DB::Manager::AuthUser->find_by(login => $employee->login);
63         if ($user) {
64           my $mail_to = trim($user->get_config_value('email'));
65
66           next if !$mail_to;
67
68           $mail_to_by_employee_id->{$employee->id}->{mail_to} = $mail_to;
69         }
70       }
71
72       if (exists $mail_to_by_employee_id->{$employee->id}) {
73         push @{ $mail_to_by_employee_id->{$employee->id}->{follow_ups} }, $follow_up;
74       }
75     }
76   }
77
78   foreach (keys %$mail_to_by_employee_id) {
79     my ($message, $content_type) = $self->generate_message($mail_to_by_employee_id->{$_}->{follow_ups});
80
81     my $mail              = Mailer->new;
82     $mail->{from}         = $self->params->{email_from};
83     $mail->{to}           = $mail_to_by_employee_id->{$_}->{mail_to};
84     $mail->{bcc}          = SL::DB::Default->get->global_bcc;
85     $mail->{subject}      = $self->params->{email_subject};
86     $mail->{message}      = $message;
87     $mail->{content_type} = $content_type;
88
89     my $error = $mail->send;
90
91     if ($error) {
92       push @{ $self->{job_errors} }, $error;
93     }
94   }
95
96   my $msg = t8('Follow ups reminder sent.');
97
98   # die if errors exists
99   if (@{ $self->{job_errors} }) {
100     $msg .= t8('The following errors occurred:');
101     $msg .= join "\n", @{ $self->{job_errors} };
102     die $msg . "\n";
103   }
104
105   return $msg;
106 }
107
108 # helper
109 sub initialize_params {
110   my ($self, $data) = @_;
111
112   # valid parameters with default values
113   my %valid_params = (
114     from_date      => undef,
115     to_date        => DateTime->today_local->to_kivitendo,
116     email_from     => $::lx_office_conf{follow_up_reminder}->{email_from},
117     email_subject  => $::lx_office_conf{follow_up_reminder}->{email_subject},
118     email_template => $::lx_office_conf{follow_up_reminder}->{email_template},
119   );
120
121   # check user input param names
122   foreach my $param (keys %$data) {
123     die "Not a valid parameter: $param" unless exists $valid_params{$param};
124   }
125
126   # set defaults
127   $self->params(
128     { map { ($_ => $data->{$_} // $valid_params{$_}) } keys %valid_params }
129   );
130
131   # convert date from string to object
132   my ($from_date, $to_date);
133   try {
134     if ($self->params->{from_date}) {
135       $from_date = DateTime->from_kivitendo($self->params->{from_date});
136       # Not undef and no other type.
137       die unless ref $from_date eq 'DateTime';
138     }
139     if ($self->params->{to_date}) {
140       $to_date = DateTime->from_kivitendo($self->params->{to_date});
141       # Not undef and no other type.
142       die unless ref $to_date eq 'DateTime';
143     }
144   } catch {
145     die t8("Cannot convert date.") ."\n" .
146         t8("Input from string: #1", $self->params->{from_date}) . "\n" .
147         t8("Input to string: #1",   $self->params->{to_date})   . "\n" .
148         t8("Details: #1", $_);
149   };
150
151   $self->params->{from_date} = $from_date;
152   $self->params->{to_date}   = $to_date;
153
154   $self->params->{email_from} = trim($self->params->{email_from});
155   die t8('No email sender address given.') if !$self->params->{email_from};
156
157   return $self->params;
158 }
159
160 sub generate_message {
161   my ($self, $follow_ups) = @_;
162
163   # Force scripts/locales.pl to parse this template:
164   # parse_html_template('fu/follow_up_reminder_mail')
165   my $email_template = $self->params->{email_template};
166   my $template       = 'fu/follow_up_reminder_mail';
167   my $content_type   = 'text/html';
168   my $render_type    = 'html';
169
170   if ($email_template) {
171     my $content;
172     try {
173       $content = slurp $email_template;
174
175     } catch {
176       $::lxdebug->message(LXDebug->WARN(), 'Cannot read template file. Error: ' . $_);
177     };
178
179     return $self->generate_message_simple_text($follow_ups) if !$content;
180
181     $template     = \$content;
182     $content_type = $email_template =~ m/.html$/ ? 'text/html' : 'text/plain';
183     $render_type  = $email_template =~ m/.html$/ ? 'html'      : 'text';
184   }
185
186   my $output = SL::Presenter->get->render($template,
187                                           {type => $render_type},
188                                           follow_ups => $follow_ups);
189
190   return ($output, $content_type);
191 }
192
193 sub generate_message_simple_text {
194   my ($self, $follow_ups) = @_;
195
196   my $output = t8('Unfinished follow-ups') . ":\n";
197   foreach my $follow_up (@$follow_ups) {
198     $output .= t8('Follow-Up Date') . ': ' . $follow_up->follow_up_date_as_date;
199     $output .= ': ' . $follow_up->note->subject;
200     $output .= ': (' . t8('by') . ' ' . $follow_up->created_by_employee->safe_name . ')';
201     $output .= ' (' . $follow_up->{link} . ')';
202     $output .= "\n";
203   }
204
205   $output .= "\n\n";
206
207   return ($output, 'text/plain');
208 }
209
210 1;
211
212 __END__
213
214 =pod
215
216 =encoding utf8
217
218 =head1 NAME
219
220 SL::BackgroundJob::SendFollowUpReminder - Send emails to employees to
221 remind them of due follow ups
222
223 =head1 SYNOPSIS
224
225 Get all due follow ups. This are the ones that are not done yet and have a
226 follow up date until today (configurable, see below).
227 For each employee addreesed by this follow ups, an email is send (if the
228 employees email address is configured).
229
230 =head1 CONFIGURATION
231
232 In the kivitendo configuration file (C<config/kivitendo.conf>) in the section
233 "follow_up_reminder" some settings can be made:
234
235 =over 4
236
237 =item C<email_from>
238
239 The senders email address. This information can be overwriten by
240 data provided to the background job.
241
242 =item C<email_subject>
243
244 The subject of the emails. This information can be overwriten by
245 data provided to the background job.
246
247 =item C<email_template>
248
249 A template file used to generate the emails content. It will be given an
250 array of the follow ups in the template variable C<follow_ups>.
251 You can provide a text or a html template.
252 If not given, it defaults to C<fu/follow_up_reminder_mail.html> in the
253 webpages directory.
254 If given, but not found, a simple text version will be generated as
255 content.
256 This information can be overwriten by data provided to the background job.
257
258 =back
259
260 Also some data can be provided to configure this backgroung job.
261 If there is data provided and it cannot be validated the background job
262 fails.
263
264 Example:
265
266   from_date: 01.01.2022
267   to_date: 01.07.2022
268   email_subject: To-Do
269
270 =over 4
271
272 =item C<from_date>
273
274 The date from which on follow ups not done yet should be collected. It defaults
275 undef which means from the beginning on.
276
277 Example (format depends on your settings):
278
279 from_date: 01.01.2022
280
281 =item C<to_date>
282
283 The date till which follow ups not done yet should be collected. It defaults
284 to today.
285
286 Example (format depends on your settings):
287
288 to_date: 01.07.2022
289
290 =item C<email_from>
291
292 The senders email address. It defaults to the one given in the kivitendo
293 configuration file (see above). This information must be provided some
294 how.
295
296 Example:
297
298 email_from: bernd@kivitendo.de
299
300 =item C<email_subject>
301
302 The subject of the emails.
303 It defaults to the one given in the kvitendo configuration file (see above).
304
305 email_subject: To-Do
306
307 =item C<email_template>
308
309 A template file used to generate the emails content. It will be given an
310 array of the follow ups in the template variable C<follow_ups>. You can
311 provide a text or a html template.
312 It defaults to the one given in the kvitendo configuration file (see above).
313
314 email_template: templates/my_templates/my_reminder_template.txt
315
316 =back
317
318 =head1 AUTHOR
319
320 Bernd Bleßmann E<lt>bernd@kivitendo-premium.deE<gt>
321
322 =cut