[freeside-commits] branch master updated. 94a16efc8164c9ba8a9bc027ba9485027a6a8b7b

Mark Wells mark at 420.am
Fri Aug 26 17:29:21 PDT 2016


The branch, master has been updated
       via  94a16efc8164c9ba8a9bc027ba9485027a6a8b7b (commit)
      from  a91bf2fe8faae6f2c71e0a774218774bafce13e7 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 94a16efc8164c9ba8a9bc027ba9485027a6a8b7b
Author: Mark Wells <mark at freeside.biz>
Date:   Fri Aug 26 17:29:14 2016 -0700

    saved searches, core stuff, #72101

diff --git a/FS/FS/Mason.pm b/FS/FS/Mason.pm
index 245bdea..e8a1af6 100644
--- a/FS/FS/Mason.pm
+++ b/FS/FS/Mason.pm
@@ -415,6 +415,8 @@ if ( -e $addl_handler_use_file ) {
   use FS::part_svc_msgcat;
   use FS::commission_schedule;
   use FS::commission_rate;
+  use FS::saved_search;
+  use FS::saved_search_option;
   # Sammath Naur
 
   if ( $FS::Mason::addl_handler_use ) {
diff --git a/FS/FS/Schema.pm b/FS/FS/Schema.pm
index 2aa0b63..a74de4c 100644
--- a/FS/FS/Schema.pm
+++ b/FS/FS/Schema.pm
@@ -7482,6 +7482,44 @@ sub tables_hashref {
                           },
                         ],
     },
+
+    'saved_search' => {
+      'columns' => [
+        'searchnum',    'serial',  '',          '', '', '',
+        'usernum',      'int',     'NULL',      '', '', '',
+        'searchname',   'varchar', '',     $char_d, '', '',
+        'path',         'varchar', '',     $char_d, '', '',
+        'disabled',     'char',    'NULL',       1, '', '',
+        'freq',         'varchar', 'NULL',      16, '', '',
+        'last_sent',    'int',     'NULL',      '', '', '',
+        'format',       'varchar', 'NULL',      32, '', '',
+      ],
+      'primary_key'   => 'searchnum',
+      'unique'        => [],
+      'index'         => [],
+      'foreign_keys'  => [
+                           { columns => [ 'usernum' ],
+                             table   => 'access_user',
+                           },
+                         ],
+    },
+
+    'saved_search_option' => {
+      'columns' => [
+        'optionnum',  'serial',  '',          '', '', '',
+        'searchnum',  'int',     '',          '', '', '',
+        'optionname', 'varchar', '', $char_d, '', '', 
+        'optionvalue', 'text', 'NULL', '', '', '', 
+      ],
+      'primary_key'   => 'optionnum',
+      'unique'        => [ [ 'searchnum', 'optionname' ] ],
+      'index'         => [],
+      'foreign_keys'  => [
+                           { columns => [ 'searchnum' ],
+                             table   => 'saved_search',
+                           },
+                         ],
+    },
  
     # name type nullability length default local
 
diff --git a/FS/FS/saved_search.pm b/FS/FS/saved_search.pm
new file mode 100644
index 0000000..075d759
--- /dev/null
+++ b/FS/FS/saved_search.pm
@@ -0,0 +1,249 @@
+package FS::saved_search;
+use base qw( FS::option_Common FS::Record );
+
+use strict;
+use FS::Record qw( qsearch qsearchs );
+use FS::Conf;
+use Class::Load 'load_class';
+use URI::Escape;
+use DateTime;
+use Try::Tiny;
+
+=head1 NAME
+
+FS::saved_search - Object methods for saved_search records
+
+=head1 SYNOPSIS
+
+  use FS::saved_search;
+
+  $record = new FS::saved_search \%hash;
+  $record = new FS::saved_search { 'column' => 'value' };
+
+  $error = $record->insert;
+
+  $error = $new_record->replace($old_record);
+
+  $error = $record->delete;
+
+  $error = $record->check;
+
+=head1 DESCRIPTION
+
+An FS::saved_search object represents a search (a page in the backoffice
+UI, typically under search/ or browse/) which a user has saved for future
+use or periodic email delivery.
+
+FS::saved_search inherits from FS::Record.  The following fields are
+currently supported:
+
+=over 4
+
+=item searchnum
+
+primary key
+
+=item usernum
+
+usernum of the L<FS::access_user> that created the search. Currently, email
+reports will only be sent to this user.
+
+=item searchname
+
+A descriptive name.
+
+=item path
+
+The path to the page within the Mason document space.
+
+=item disabled
+
+'Y' to hide the search from the user's Reports / Saved menu.
+
+=item freq
+
+A frequency for email delivery of this report: daily, weekly, or
+monthly, or null to disable it.
+
+=item last_sent
+
+The timestamp of the last time this report was sent.
+
+=item format
+
+'html', 'xls', or 'csv'. Not all reports support all of these.
+
+=back
+
+=head1 METHODS
+
+=over 4
+
+=item new HASHREF
+
+Creates a new saved search.  To add it to the database, see L<"insert">.
+
+Note that this stores the hash reference, not a distinct copy of the hash it
+points to.  You can ask the object for a copy with the I<hash> method.
+
+=cut
+
+sub table { 'saved_search'; }
+
+=item insert
+
+Adds this record to the database.  If there is an error, returns the error,
+otherwise returns false.
+
+=item delete
+
+Delete this record from the database.
+
+=item replace OLD_RECORD
+
+Replaces the OLD_RECORD with this one in the database.  If there is an error,
+returns the error, otherwise returns false.
+
+=cut
+
+# the replace method can be inherited from FS::Record
+
+=item check
+
+Checks all fields to make sure this is a valid example.  If there is
+an error, returns the error, otherwise returns false.  Called by the insert
+and replace methods.
+
+=cut
+
+# the check method should currently be supplied - FS::Record contains some
+# data checking routines
+
+sub check {
+  my $self = shift;
+
+  my $error = 
+    $self->ut_numbern('searchnum')
+    || $self->ut_number('usernum')
+    #|| $self->ut_foreign_keyn('usernum', 'access_user', 'usernum')
+    || $self->ut_text('searchname')
+    || $self->ut_text('path')
+    || $self->ut_flag('disabled')
+    || $self->ut_enum('freq', [ '', 'daily', 'weekly', 'monthly' ])
+    || $self->ut_numbern('last_sent')
+    || $self->ut_enum('format', [ '', 'html', 'csv', 'xls' ])
+  ;
+  return $error if $error;
+
+  $self->SUPER::check;
+}
+
+=item next_send_date
+
+Returns the next date this report should be sent next. If it's not set for
+periodic email sending, returns undef. If it is set up but has never been
+sent before, returns zero.
+
+=cut
+
+sub next_send_date {
+  my $self = shift;
+  my $freq = $self->freq or return undef;
+  return 0 unless $self->last_sent;
+  my $dt = DateTime->from_epoch(epoch => $self->last_sent);
+  $dt->truncate(to => 'day');
+  if ($freq eq 'daily') {
+    $dt->add(days => 1);
+  } elsif ($freq eq 'weekly') {
+    $dt->add(weeks => 1);
+  } elsif ($freq eq 'monthly') {
+    $dt->add(months => 1);
+  }
+  $dt->epoch;
+}
+
+=item query_string
+
+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;
+
+  my $type = $self->format;
+  $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;
+}
+
+=item render
+
+Returns the report content as an HTML or Excel file.
+
+=cut
+
+sub render {
+  my $self = shift;
+  my $outbuf;
+
+  # delayed loading
+  load_class('FS::Mason');
+  RT::LoadConfig();
+  RT::Init();
+
+  # do this before setting QUERY_STRING/FSURL
+  my ($fs_interp) = FS::Mason::mason_interps('standalone',
+    outbuf => \$outbuf
+  );
+  $fs_interp->error_mode('fatal');
+  $fs_interp->error_format('text');
+
+  local $FS::CurrentUser::CurrentUser = $self->access_user;
+  local $FS::Mason::Request::QUERY_STRING = $self->query_string;
+  local $FS::Mason::Request::FSURL = ''; #?
+#  local $ENV{SERVER_NAME} = 'localhost'; #?
+#  local $ENV{SCRIPT_NAME} = '/freeside'. $self->path;
+
+  my $mason_request = $fs_interp->make_request(comp => $self->path);
+
+  local $@;
+  eval { $mason_request->exec(); };
+  if ($@) {
+    my $error = $@;
+    if ( ref($error) eq 'HTML::Mason::Exception' ) {
+      $error = $error->message;
+    }
+
+    warn "Error rendering " . $self->path .
+         " for " . $self->access_user->username .
+         ":\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>
+  <p>' . $self->path . '?' . $self->query_string . '</p>
+  <p>' . $_ . '</p>';
+  }
+
+  return $outbuf;
+}
+
+=back
+
+=head1 SEE ALSO
+
+L<FS::Record>
+
+=cut
+
+1;
+
diff --git a/FS/FS/saved_search_option.pm b/FS/FS/saved_search_option.pm
new file mode 100644
index 0000000..f349af3
--- /dev/null
+++ b/FS/FS/saved_search_option.pm
@@ -0,0 +1,124 @@
+package FS::saved_search_option;
+use base qw( FS::Record );
+
+use strict;
+use FS::Record qw( qsearch qsearchs );
+
+=head1 NAME
+
+FS::saved_search_option - Object methods for saved_search_option records
+
+=head1 SYNOPSIS
+
+  use FS::saved_search_option;
+
+  $record = new FS::saved_search_option \%hash;
+  $record = new FS::saved_search_option { 'column' => 'value' };
+
+  $error = $record->insert;
+
+  $error = $new_record->replace($old_record);
+
+  $error = $record->delete;
+
+  $error = $record->check;
+
+=head1 DESCRIPTION
+
+An FS::saved_search_option object represents a CGI parameter for a report
+saved in L<FS::saved_search>.  FS::saved_search_option inherits from
+FS::Record.  The following fields are currently supported:
+
+=over 4
+
+=item optionnum
+
+primary key
+
+=item searchnum
+
+searchnum
+
+=item optionname
+
+optionname
+
+=item optionvalue
+
+optionvalue
+
+
+=back
+
+=head1 METHODS
+
+=over 4
+
+=item new HASHREF
+
+Creates a new parameter.  To add the record to the database, see
+L<"insert">.
+
+Note that this stores the hash reference, not a distinct copy of the hash it
+points to.  You can ask the object for a copy with the I<hash> method.
+
+=cut
+
+# the new method can be inherited from FS::Record, if a table method is defined
+
+sub table { 'saved_search_option'; }
+
+=item insert
+
+Adds this record to the database.  If there is an error, returns the error,
+otherwise returns false.
+
+=item delete
+
+Delete this record from the database.
+
+=item replace OLD_RECORD
+
+Replaces the OLD_RECORD with this one in the database.  If there is an error,
+returns the error, otherwise returns false.
+
+=item check
+
+Checks all fields to make sure this is a valid example.  If there is
+an error, returns the error, otherwise returns false.  Called by the insert
+and replace methods.
+
+=cut
+
+# the check method should currently be supplied - FS::Record contains some
+# data checking routines
+
+sub check {
+  my $self = shift;
+
+# unpack these from the format used by CGI
+  my $optionvalue = $self->optionvalue;
+  $optionvalue =~ s/\0/\n/g;
+
+  my $error = 
+    $self->ut_numbern('optionnum')
+    || $self->ut_number('searchnum')
+#   || $self->ut_foreign_key('searchnum', 'saved_search', 'searchnum')
+    || $self->ut_text('optionname')
+    || $self->ut_textn('optionvalue')
+  ;
+  return $error if $error;
+
+  $self->SUPER::check;
+}
+
+=back
+
+=head1 SEE ALSO
+
+L<FS::Record>
+
+=cut
+
+1;
+
diff --git a/FS/MANIFEST b/FS/MANIFEST
index 4184b9c..d06f263 100644
--- a/FS/MANIFEST
+++ b/FS/MANIFEST
@@ -874,3 +874,7 @@ FS/commission_schedule.pm
 t/commission_schedule.t
 FS/commission_rate.pm
 t/commission_rate.t
+FS/saved_search.pm
+t/saved_search.t
+FS/saved_search_option.pm
+t/saved_search_option.t
diff --git a/FS/t/saved_search.t b/FS/t/saved_search.t
new file mode 100644
index 0000000..8155c6d
--- /dev/null
+++ b/FS/t/saved_search.t
@@ -0,0 +1,5 @@
+BEGIN { $| = 1; print "1..1\n" }
+END {print "not ok 1\n" unless $loaded;}
+use FS::saved_search;
+$loaded=1;
+print "ok 1\n";
diff --git a/FS/t/saved_search_option.t b/FS/t/saved_search_option.t
new file mode 100644
index 0000000..f30bfb8
--- /dev/null
+++ b/FS/t/saved_search_option.t
@@ -0,0 +1,5 @@
+BEGIN { $| = 1; print "1..1\n" }
+END {print "not ok 1\n" unless $loaded;}
+use FS::saved_search_option;
+$loaded=1;
+print "ok 1\n";

-----------------------------------------------------------------------

Summary of changes:
 FS/FS/Mason.pm                                     |    2 +
 FS/FS/Schema.pm                                    |   38 +++
 FS/FS/saved_search.pm                              |  249 ++++++++++++++++++++
 ...part_pkg_currency.pm => saved_search_option.pm} |   57 ++---
 FS/MANIFEST                                        |    4 +
 FS/t/{AccessRight.t => saved_search.t}             |    2 +-
 FS/t/{AccessRight.t => saved_search_option.t}      |    2 +-
 7 files changed, 317 insertions(+), 37 deletions(-)
 create mode 100644 FS/FS/saved_search.pm
 copy FS/FS/{part_pkg_currency.pm => saved_search_option.pm} (60%)
 copy FS/t/{AccessRight.t => saved_search.t} (82%)
 copy FS/t/{AccessRight.t => saved_search_option.t} (77%)




More information about the freeside-commits mailing list