summaryrefslogtreecommitdiff
path: root/FS/FS/saved_search.pm
diff options
context:
space:
mode:
authorMark Wells <mark@freeside.biz>2016-09-08 11:25:47 -0700
committerMark Wells <mark@freeside.biz>2016-09-08 11:25:47 -0700
commit4b75f33fd6c2d0fecf8714f588f2d6d200aa4d47 (patch)
tree9edc7d3801373d6202266b95c4f5194183e712b8 /FS/FS/saved_search.pm
parent9a9f45c82bc7901cfa94b6e64a2e3e4d5b15abff (diff)
add email delivery of saved searches, #72101
Diffstat (limited to 'FS/FS/saved_search.pm')
-rw-r--r--FS/FS/saved_search.pm92
1 files changed, 79 insertions, 13 deletions
diff --git a/FS/FS/saved_search.pm b/FS/FS/saved_search.pm
index 075d759..252dc71 100644
--- a/FS/FS/saved_search.pm
+++ b/FS/FS/saved_search.pm
@@ -1,13 +1,15 @@
package FS::saved_search;
-use base qw( FS::option_Common FS::Record );
+use base qw( FS::Record );
use strict;
use FS::Record qw( qsearch qsearchs );
use FS::Conf;
+use FS::Log;
+use FS::Misc qw(send_email);
+use MIME::Entity;
use Class::Load 'load_class';
use URI::Escape;
use DateTime;
-use Try::Tiny;
=head1 NAME
@@ -56,6 +58,10 @@ A descriptive name.
The path to the page within the Mason document space.
+=item params
+
+The query string for the search.
+
=item disabled
'Y' to hide the search from the user's Reports / Saved menu.
@@ -128,6 +134,7 @@ sub check {
#|| $self->ut_foreign_keyn('usernum', 'access_user', 'usernum')
|| $self->ut_text('searchname')
|| $self->ut_text('path')
+ || $self->ut_textn('params') # URL-escaped, so ut_textn
|| $self->ut_flag('disabled')
|| $self->ut_enum('freq', [ '', 'daily', 'weekly', 'monthly' ])
|| $self->ut_numbern('last_sent')
@@ -138,6 +145,14 @@ sub check {
$self->SUPER::check;
}
+sub replace_check {
+ my ($new, $old) = @_;
+ if ($new->usernum != $old->usernum) {
+ return "can't change owner of a saved search";
+ }
+ '';
+}
+
=item next_send_date
Returns the next date this report should be sent next. If it's not set for
@@ -168,8 +183,6 @@ Returns the CGI query string for the parameters to this report.
=cut
-# multivalued options are newline-separated in the database
-
sub query_string {
my $self = shift;
@@ -177,12 +190,7 @@ sub query_string {
$type = 'html-print' if $type eq '' || $type eq 'html';
$type = '.xls' if $type eq 'xls';
my $query = "_type=$type";
- my %options = $self->options;
- foreach my $k (keys %options) {
- foreach my $v (split("\n", $options{$k})) {
- $query .= ';' . uri_escape($k) . '=' . uri_escape($v);
- }
- }
+ $query .= ';' . $self->params if $self->params;
$query;
}
@@ -194,6 +202,7 @@ Returns the report content as an HTML or Excel file.
sub render {
my $self = shift;
+ my $log = FS::Log->new('FS::saved_search::render');
my $outbuf;
# delayed loading
@@ -214,7 +223,7 @@ sub render {
# local $ENV{SERVER_NAME} = 'localhost'; #?
# local $ENV{SCRIPT_NAME} = '/freeside'. $self->path;
- my $mason_request = $fs_interp->make_request(comp => $self->path);
+ my $mason_request = $fs_interp->make_request(comp => '/' . $self->path);
local $@;
eval { $mason_request->exec(); };
@@ -224,9 +233,9 @@ sub render {
$error = $error->message;
}
- warn "Error rendering " . $self->path .
+ $log->error("Error rendering " . $self->path .
" for " . $self->access_user->username .
- ":\n$error\n";
+ ":\n$error\n");
# send it to the user anyway, so there's a way to diagnose the error
$outbuf = '<h3>Error</h3>
<p>There was an error generating the report "'.$self->searchname.'".</p>
@@ -237,6 +246,63 @@ sub render {
return $outbuf;
}
+=item send
+
+Sends the search by email. If anything fails, logs and returns an error.
+
+=cut
+
+sub send {
+ my $self = shift;
+ my $log = FS::Log->new('FS::saved_search::send');
+ my $conf = FS::Conf->new;
+ my $user = $self->access_user;
+ my $username = $user->username;
+ my $user_email = $user->option('email_address');
+ my $error;
+ if (!$user_email) {
+ $error = "User '$username' has no email address.";
+ $log->error($error);
+ return $error;
+ }
+ $log->debug('Rendering saved search');
+ my $content = $self->render;
+ # XXX come back to this for content-type options
+ my $part = MIME::Entity->build(
+ 'Type' => 'text/html',
+ 'Encoding' => 'quoted-printable', # change this for spreadsheet
+ 'Disposition' => 'inline',
+ 'Data' => $content,
+ );
+
+ my %email_param = (
+ 'from' => $conf->config('invoice_from'),
+ 'to' => $user_email,
+ 'subject' => $self->searchname,
+ 'nobody' => 1,
+ 'mimeparts' => [ $part ],
+ );
+
+ $log->debug('Sending to '.$user_email);
+ $error = send_email(%email_param);
+
+ # update the timestamp
+ $self->set('last_sent', time);
+ $error ||= $self->replace;
+ if ($error) {
+ $log->error($error);
+ return $error;
+ }
+
+}
+
+sub queueable_send {
+ my $searchnum = shift;
+ my $self = FS::saved_search->by_key($searchnum)
+ or die "searchnum $searchnum not found\n";
+ $self->send;
+}
+
=back
=head1 SEE ALSO