[freeside-commits] branch master updated. 9ea31f98372bc897fd0b4d7e63284eecabf27aa2

Mitch Jackson mitch at freeside.biz
Mon Sep 17 18:36:41 PDT 2018


The branch, master has been updated
       via  9ea31f98372bc897fd0b4d7e63284eecabf27aa2 (commit)
      from  643d1b29847685065eb9b0d46a1129a885147ec0 (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 9ea31f98372bc897fd0b4d7e63284eecabf27aa2
Author: Mitch Jackson <mitch at freeside.biz>
Date:   Mon Sep 17 21:30:15 2018 -0400

    RT# 78547 Future autobill report - report runs in job queue

diff --git a/FS/FS/Report/Queued/FutureAutobill.pm b/FS/FS/Report/Queued/FutureAutobill.pm
new file mode 100644
index 000000000..82c902172
--- /dev/null
+++ b/FS/FS/Report/Queued/FutureAutobill.pm
@@ -0,0 +1,132 @@
+package FS::Report::Queued::FutureAutobill;
+use strict;
+use warnings;
+use vars qw( $job );
+
+use FS::Conf;
+use FS::cust_main;
+use FS::cust_main::Location;
+use FS::cust_payby;
+use FS::CurrentUser;
+use FS::Log;
+use FS::Mason qw(mason_interps);
+use FS::Record qw( qsearch );
+use FS::UI::Web;
+use FS::UID qw( dbh );
+
+use DateTime;
+use File::Temp;
+use Data::Dumper;
+use HTML::Entities qw( encode_entities );
+
+=head1 NAME
+
+FS::Report::Queued::FutureAutobill - Future Auto-Bill Transactions Report
+
+=head1 DESCRIPTION
+
+Future Autobill report generated within the job queue.
+
+Report results are saved to temp storage as a Mason fragment
+that is rendered by the queued report viewer.
+
+For every customer with a valid auto-bill payment method,
+report runs bill_and_collect() for each day, from today through
+the report target date.  After recording the results, all
+operations are rolled back.
+
+This report relies on the ability to safely run bill_and_collect(),
+with all exports and messaging disabled, and then to roll back the
+results.
+
+=head1 PARAMETERS
+
+C<agentnum>, C<target_date>
+
+=cut
+
+sub make_report {
+  $job = shift;
+  my $param = shift;
+  my $outbuf;
+  my $DEBUG = 0;
+
+  my $time_begin = time();
+
+  my $report_fh = File::Temp->new(
+    TEMPLATE => 'report.future_autobill.XXXXXXXX',
+    DIR      => sprintf( '%s/cache.%s', $FS::Conf::base_dir, $FS::UID::datasrc ),
+    UNLINK   => 0
+  ) or die "Cannot create report file: $!";
+
+  if ( $DEBUG ) {
+    warn Dumper( $job );
+    warn Dumper( $param );
+    warn $report_fh;
+    warn $report_fh->filename;
+  }
+
+  my $curuser = FS::CurrentUser->load_user( $param->{CurrentUser} )
+    or die 'Unable to set report user';
+
+  my ( $fs_interp ) = FS::Mason::mason_interps(
+    'standalone',
+    outbuf => \$outbuf,
+  );
+  $fs_interp->error_mode('fatal');
+  $fs_interp->error_format('text');
+
+  $FS::Mason::Request::QUERY_STRING = sprintf(
+    'target_date=%s&agentnum=%s',
+    encode_entities( $param->{target_date} ),
+    encode_entities( $param->{agentnum} || '' ),
+  );
+  $FS::Mason::Request::FSURL = $param->{RootURL};
+
+  my $mason_request = $fs_interp->make_request(
+    comp => '/search/future_autobill.html'
+  );
+
+  {
+    local $@;
+    eval{ $mason_request->exec() };
+    if ( $@ ) {
+      my $error = ref $@ eq 'HTML::Mason::Exception' ? $@->error : $@;
+
+      my $log = FS::Log->new('FS::Report::Queued::FutureAutobill');
+      $log->error(
+        "Error generating report: $FS::Mason::Request::QUERY_STRING $error"
+      );
+      die $error;
+    }
+  }
+
+  my $report_fn;
+  if ( $report_fh->filename =~ /report\.(future_autobill.+)$/ ) {
+      $report_fn = $1
+  } else {
+    die 'Error parsing report filename '.$report_fh->filename;
+  }
+
+  my $report_title = FS::cust_payby->future_autobill_report_title();
+  my $time_rendered = time() - $time_begin;
+
+  if ( $DEBUG ) {
+    warn "Generated content:\n";
+    warn $outbuf;
+    warn $report_fn;
+    warn $report_title;
+  }
+
+  print $report_fh qq{<% include("/elements/header.html", '$report_title') %>\n};
+  print $report_fh $outbuf;
+  print $report_fh qq{<!-- Time to render report $time_rendered seconds -->};
+  print $report_fh qq{<% include("/elements/footer.html") %>\n};
+
+  die sprintf
+    "<a href=%s/misc/queued_report.html?report=%s>view</a>\n",
+    $param->{RootURL},
+    $report_fn;
+}
+
+1;
diff --git a/FS/FS/UI/Web.pm b/FS/FS/UI/Web.pm
index 6cc04b9de..54128682e 100644
--- a/FS/FS/UI/Web.pm
+++ b/FS/FS/UI/Web.pm
@@ -743,6 +743,7 @@ use FS::CurrentUser;
 use FS::Record qw(qsearchs);
 use FS::queue;
 use FS::CGI qw(rooturl);
+use FS::Report::Queued::FutureAutobill;
 
 $DEBUG = 0;
 
diff --git a/httemplate/search/elements/grid-report.html b/httemplate/search/elements/grid-report.html
index b1e543012..efc009725 100644
--- a/httemplate/search/elements/grid-report.html
+++ b/httemplate/search/elements/grid-report.html
@@ -141,13 +141,17 @@ Usage:
   $m->print($output);
 </%perl>
 % } else {
+% unless ( $suppress_header ) {
 <& /elements/header.html, $title &>
+% }
 <% $head %>
 % my $myself = $cgi->self_url;
+% unless ( $suppress_header ) {
 <P ALIGN="right" CLASS="noprint">
 Download full reports<BR>
 as <A HREF="<% "$myself;_type=xls" %>">Excel spreadsheet</A><BR>
 </P>
+% }
 <style type="text/css">
 .report * {
   background-color: #f8f8f8;
@@ -169,8 +173,10 @@ as <A HREF="<% "$myself;_type=xls" %>">Excel spreadsheet</A><BR>
 %     next if !ref($cell); # placeholders
 %     my $td = $cell->{header} ? 'th' : 'td';
 %     my $style = '';
-%     $style .= " rowspan=".$cell->{rowspan} if $cell->{rowspan} > 1;
-%     $style .= " colspan=".$cell->{colspan} if $cell->{colspan} > 1;
+%     $style .= " rowspan=".$cell->{rowspan}
+%       if exists $cell->{rowspan} && $cell->{rowspan} > 1;
+%     $style .= " colspan=".$cell->{colspan}
+%       if exists $cell->{colspan} && $cell->{colspan} > 1;
 %     $style .= ' class="' . $cell->{class} . '"' if $cell->{class};
 % if ($cell->{bypass_filter}) {
       <<%$td%><%$style%>><% $cell->{value} %></<%$td%>>
@@ -182,8 +188,10 @@ as <A HREF="<% "$myself;_type=xls" %>">Excel spreadsheet</A><BR>
 % }
 </table>
 <% $foot %>
+% unless ( $suppress_footer ) {
 <& /elements/footer.html &>
 % }
+% }
 <%args>
 $title
 @rows
@@ -192,4 +200,6 @@ $head => ''
 $foot => ''
 $table_width => "100%"
 $table_class => "report"
+$suppress_header => undef
+$suppress_footer => undef
 </%args>
diff --git a/httemplate/search/future_autobill.html b/httemplate/search/future_autobill.html
index d4ad8e524..1f3862fbc 100644
--- a/httemplate/search/future_autobill.html
+++ b/httemplate/search/future_autobill.html
@@ -11,7 +11,12 @@ This report relies on the ability to safely run bill_and_collect(),
 with all exports and messaging disabled, and then to roll back the
 results.
 
+This report takes time.  If 200 customers have automatic
+payment methods, and requester is looking one week ahead,
+there will be 1,400 billing and payment cycles simulated
+
 </%doc>
+<h4><% $report_subtitle %></h4>
 <& elements/grid-report.html,
   title => $report_title,
   rows => \@rows,
@@ -27,17 +32,25 @@ results.
       td.gridreport { margin: 0 .2em; padding: 0 .4em; }
     </style>
   ',
+  suppress_header => $job ? 1 : 0,
+  suppress_footer => $job ? 1 : 0,
 &>
 
 <%init>
+  use DateTime;
+  use FS::Misc::Savepoint;
+  use FS::Report::Queued::FutureAutobill;
   use FS::UID qw( dbh );
 
   die "access denied"
     unless $FS::CurrentUser::CurrentUser->access_right('Financial reports');
 
+  my $job = $FS::Report::Queued::FutureAutobill::job;
+
+  $job->update_statustext('0,Finding customers') if $job;
+
   my $DEBUG = $cgi->param('DEBUG') || 0;
 
-  my $report_title = FS::cust_payby->future_autobill_report_title;
   my $agentnum = $cgi->param('agentnum')
     if $cgi->param('agentnum') =~ /^\d+/;
 
@@ -60,16 +73,20 @@ results.
 
   # Get target date from form
   if ($cgi->param('target_date')) {
+    # DateTime::Format::DateParse would be better
     my ($mm, $dd, $yy) = split /[\-\/]/,$cgi->param('target_date');
+    ( $yy, $mm, $dd ) = ( $mm, $dd, $yy ) if $mm > 1900;
+
     $target_dt = DateTime->new(
       month  => $mm,
       day    => $dd,
       year   => $yy,
       %noon,
-    ) if $mm && $dd & $yy;
+    ) if $mm && $dd && $yy;
 
     # Catch a date from the past: time only travels in one direction
-    $target_dt = undef if $target_dt->epoch < $now_dt->epoch;
+    $target_dt = undef
+      unless $target_dt && $now_dt && $now_dt <=  $target_dt;
   }
 
   # without a target date, default to tomorrow
@@ -77,6 +94,13 @@ results.
     $target_dt = $now_dt->clone->add( days => 1 );
   }
 
+  my $report_title = FS::cust_payby->future_autobill_report_title;
+  my $report_subtitle = sprintf(
+    '(%s through %s)',
+    $now_dt->mdy('/'),
+    $target_dt->mdy('/'),
+  );
+
   # Create a range of dates from today until the given report date
   #   (leaving the probably useless 'quick-report' mode, but disabled)
   if ( 1 || $cgi->param('multiple_billing_dates')) {
@@ -104,6 +128,9 @@ results.
       . ($agentnum ? "AND cust_main.agentnum = $agentnum" : ''),
   });
 
+  my $completion_target = scalar(keys %cust_payby) * scalar( @target_dates );
+  my $completion_progress = 0;
+
   my $fakebill_time = time();
   my %abreport;
   my @rows;
@@ -125,6 +152,9 @@ results.
     local $FS::cust_main::Billing_Realtime::BOP_TESTING = 1;
     local $FS::cust_main::Billing_Realtime::BOP_TESTING_SUCCESS = 1;
 
+    my $savepoint_label = 'future_autobill';
+    savepoint_create( $savepoint_label );
+
     warn sprintf "Report involves %s customers", scalar keys %cust_payby
       if $DEBUG;
 
@@ -153,8 +183,18 @@ results.
         );
 
         warn "!!! $error (simulating future billing)\n" if $error;
+
+        my $statustext = sprintf(
+            '%s,Simulating upcoming invoices and payments',
+            int( ( ++$completion_progress / $completion_target ) * 100 )
+        );
+        $job->update_statustext( $statustext ) if $job;
+        warn "[ $completion_progress / $completion_target ] $statustext\n"
+          if $DEBUG;
+
       }
 
+
       # Generate report rows from recorded payments in cust_pay
       for my $cust_pay (
         qsearch( cust_pay => {
@@ -206,6 +246,7 @@ results.
       #   locked at a time
 
       warn "-- custnum $custnum -- rollback()\n" if $DEBUG;
+      savepoint_rollback( $savepoint_label );
       dbh->rollback if $oldAutoCommit;
 
     } # /foreach $custnum
diff --git a/httemplate/search/report_future_autobill-queued_job.html b/httemplate/search/report_future_autobill-queued_job.html
new file mode 100644
index 000000000..d23efb5b1
--- /dev/null
+++ b/httemplate/search/report_future_autobill-queued_job.html
@@ -0,0 +1,11 @@
+<% $server->process %>
+<%init>
+
+die "access denied"
+  unless $FS::CurrentUser::CurrentUser->access_right('Financial reports');
+
+my $server = new FS::UI::Web::JSRPC
+  'FS::Report::Queued::FutureAutobill::make_report',
+  $cgi;
+
+</%init>
diff --git a/httemplate/search/report_future_autobill.html b/httemplate/search/report_future_autobill.html
index ccde299e9..28f589ee7 100644
--- a/httemplate/search/report_future_autobill.html
+++ b/httemplate/search/report_future_autobill.html
@@ -1,6 +1,9 @@
 <%doc>
 
-Display date selector for the future_autobill.html report
+Display pre-report page for the Future Auto Bill Transactions report
+
+Report runs in the queue.  Once the report is generated, user is
+redirected to the report results.
 
 </%doc>
 <% include('/elements/header.html', $report_title ) %>
@@ -14,30 +17,43 @@ Display date selector for the future_autobill.html report
 
 % } else {
 
-  <FORM ACTION="future_autobill.html" METHOD="GET">
-  <TABLE>
-  <& /elements/tr-input-date-field.html,
-    {
-      name     => 'target_date',
-      value    => $target_date,
-      label    => emt('Target billing date').': ',
-      required => 1
-    }
-  &>
-
-  <% include('/elements/tr-select-agent.html',
-              'label'         => 'For agent: ',
-              'disable_empty' => 0,
+  <FORM NAME="future_autobill" ID="future_autobill">
+    <TABLE>
+    <& /elements/tr-input-date-field.html,
+      {
+        name     => 'target_date',
+        value    => $target_date,
+        label    => emt('Target billing date').': ',
+        required => 1
+      }
+    &>
+
+    <% include('/elements/tr-select-agent.html',
+                'label'         => 'For agent: ',
+                'disable_empty' => 0,
+              )
+    %>
+    </TABLE>
+    <BR>
+
+    <INPUT ID="future_autobill_submit" TYPE="submit" VALUE="<% mt('Get Report') |h %>">
+  </FORM>
+
+  <% include( '/elements/progress-init.html',
+              'future_autobill',
+              [ qw( agentnum target_date ) ],
+              'report_future_autobill-queued_job.html',
             )
   %>
 
-  </TABLE>
-
-  <BR>
-
-  <INPUT TYPE="submit" VALUE="<% mt('Get Report') |h %>">
-
-  </FORM>
+  <script type="text/javascript">
+    $('#future_autobill').submit( function( event ) {
+      $('#future_autobill').prop( 'disabled', true );
+      $('#future_autobill_submit').prop( 'disabled', true );
+      event.preventDefault();
+      process();
+    });
+  </script>
 
 % }
 

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

Summary of changes:
 FS/FS/Report/Queued/FutureAutobill.pm              | 132 +++++++++++++++++++++
 FS/FS/UI/Web.pm                                    |   1 +
 httemplate/search/elements/grid-report.html        |  14 ++-
 httemplate/search/future_autobill.html             |  47 +++++++-
 ....cgi => report_future_autobill-queued_job.html} |   5 +-
 httemplate/search/report_future_autobill.html      |  60 ++++++----
 6 files changed, 230 insertions(+), 29 deletions(-)
 create mode 100644 FS/FS/Report/Queued/FutureAutobill.pm
 copy httemplate/search/{report_queued_newtax.cgi => report_future_autobill-queued_job.html} (58%)
 mode change 100755 => 100644




More information about the freeside-commits mailing list