[freeside-commits] branch master updated. 4d7a5f06cbab1f4f9614d9915641557f4edad1cf

Mark Wells mark at 420.am
Fri Feb 5 16:18:46 PST 2016


The branch, master has been updated
       via  4d7a5f06cbab1f4f9614d9915641557f4edad1cf (commit)
       via  af4e5e495388889f3b8d3d9bb385064fb4b6d539 (commit)
      from  d01ecfec7312a6a750f94bdebca89fb60cfd9e48 (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 4d7a5f06cbab1f4f9614d9915641557f4edad1cf
Author: Mark Wells <mark at freeside.biz>
Date:   Fri Feb 5 16:00:55 2016 -0800

    refactor CDR profit/loss report also, #40103

diff --git a/httemplate/search/customer_cdr_profit.html b/httemplate/search/customer_cdr_profit.html
index 8dc0663..c535109 100644
--- a/httemplate/search/customer_cdr_profit.html
+++ b/httemplate/search/customer_cdr_profit.html
@@ -1,121 +1,11 @@
-% if ( $cgi->param('_type') =~ /(xls)$/ ) {
-<%perl>
-  # egregious false laziness w/ search/report_tax-xls.cgi
-  my $format = $FS::CurrentUser::CurrentUser->spreadsheet_format;
-  my $filename = $cgi->url(-relative => 1);
-  $filename =~ s/\.html$//;
-  $filename .= $format->{extension};
-  http_header('Content-Type' => $format->{mime_type});
-  http_header('Content-Disposition' => qq!attachment;filename="$filename"!);
-
-  my $output = '';
-  my $XLS = IO::String->new($output);
-  my $workbook = $format->{class}->new($XLS)
-    or die "Error opening .xls file: $!";
-
-  my $worksheet = $workbook->add_worksheet('Summary');
-
-  my %format = (
-    header => {
-      size      => 11,
-      bold      => 1,
-      align     => 'center',
-      valign    => 'vcenter',
-      text_wrap => 1,
-    },
-    money => {
-      size      => 11,
-      align     => 'right',
-      valign    => 'bottom',
-      num_format=> 8,
-    },
-    '' => {},
-  );
-  my %default = (
-      font      => 'Calibri',
-      border    => 1,
-  );
-  foreach (keys %format) {
-    my %f = (%default, %{$format{$_}});
-    $format{$_} = $workbook->add_format(%f);
-    $format{"m_$_"} = $workbook->add_format(%f);
-  }
-
-  my ($r, $c) = (0, 0);
-  for my $row (@rows) {
-    $c = 0;
-    my $thisrow = shift @cells;
-    for my $cell (@$thisrow) {
-      if (!ref($cell)) {
-        # placeholder, so increment $c so that we write to the correct place
-        $c++;
-        next;
-      }
-      # format name
-      my $f = '';
-      $f = 'header' if $row->{header} or $cell->{header};
-      $f = 'money' if $cell->{format} eq 'money';
-      if ( $cell->{rowspan} > 1 or $cell->{colspan} > 1 ) {
-        my $range = xl_range_formula(
-          'Summary',
-          $r, $r - 1 + ($cell->{rowspan} || 1),
-          $c, $c - 1 + ($cell->{colspan} || 1)
-        );
-        #warn "merging $range\n";
-        $worksheet->merge_range($range, $cell->{value}, $format{"m_$f"});
-      } else {
-      #warn "writing ".xl_rowcol_to_cell($r, $c)."\n";
-        $worksheet->write( $r, $c, $cell->{value}, $format{$f} );
-      }
-      $c += $cell->{colspan} || 1;
-    } #$cell
-  $r++;
-  } #$row
-  $workbook->close;
-
-  http_header('Content-Length' => length($output));
-  $m->print($output);
-</%perl>
-% } else {
-<& /elements/header.html, $title &>
-% my $myself = $cgi->self_url;
-<P ALIGN="right" CLASS="noprint">
-Download full reports<BR>
-as <A HREF="<% "$myself;_type=xls" %>">Excel spreadsheet</A>
-</P>
-<style type="text/css">
-.report * {
-  background-color: #f8f8f8;
-  border: 1px solid #999999;
-  padding: 2px;
-}
-.report td {
-  text-align: right;
-}
-.total { background-color: #f5f6be; }
-.shaded { background-color: #c8c8c8; }
-.totalshaded { background-color: #bfc094; }
-</style>
-<table class="report" width="100%" cellspacing=0>
-% foreach my $rowinfo (@rows) {
-  <tr<% $rowinfo->{class} ? ' class="'.$rowinfo->{class}.'"' : ''%>>
-%   my $thisrow = shift @cells;
-%   foreach my $cell (@$thisrow) {
-%     next if !ref($cell); # placeholders
-%     my $td = $cell->{header} ? 'th' : 'td';
-%     my $style = '';
-%     $style .= ' class="'.$cell->{class}.'"' if $cell->{class};
-%     $style .= " rowspan=".$cell->{rowspan} if $cell->{rowspan} > 1;
-%     $style .= " colspan=".$cell->{colspan} if $cell->{colspan} > 1;
-%     $style .= ' style="color: red"' if $cell->{value} < 0;
-      <<%$td%><%$style%>><% $cell->{value} |h %></<%$td%>>
-%   }
-  </tr>
-% }
-</table>
-
-<& /elements/footer.html &>
-% }
+<& elements/grid-report.html,
+  title => $title,
+  rows  => \@rows,
+  cells => \@cells,
+  head  => $head,
+  # would be better handled with Mason inheritance? consider this. easy enough
+  # to change it at this point.
+&>
 <%init>
 
 die "access denied"
@@ -213,7 +103,11 @@ foreach my $cust_main (@cust_main) { # correspond to cross_params
     for my $item (0..3) { # recur/recur_cost/usage/usage_cost
       my $value = $data->{data}[$item][$col][$row];
       $skip = 0 if abs($value) > 0.005;
-      push @thisrow, { value => sprintf('%0.2f', $value), format => 'money' };
+      push @thisrow, {
+        value => sprintf('%0.2f', $value),
+        format => 'money',
+        class => ($value < 0 ? 'negative' : ''),
+      };
       $total[$col * 5 + $item] += $value;
       $profit += (($item % 2) ? -1 : 1) * $value;
     } #item
@@ -250,4 +144,9 @@ for my $col (0..($ncols * 5)-1) { # month and recur/recur_cost/usage/usage_cost/
 }
 push @cells, \@thisrow;
 
+my $head = q[
+<style>
+  .negative { color: red }
+</style>
+];
 </%init>
diff --git a/httemplate/search/elements/grid-report.html b/httemplate/search/elements/grid-report.html
index cb06b2b..98e8178 100644
--- a/httemplate/search/elements/grid-report.html
+++ b/httemplate/search/elements/grid-report.html
@@ -5,6 +5,9 @@ which the user can request as an Excel spreadsheet. /elements/header.html
 and /elements/footer.html are included automatically, so don't include them
 again.
 
+This element defines "total", "shaded", and "totalshaded" CSS classes. For
+anything else, insert a <style> element via the 'head' argument.
+
 Usage:
 
 <& elements/grid-report.html,
@@ -21,7 +24,7 @@ Usage:
         header => 1,
         rowspan => 2,
         colspan => 3,
-        class => 'highlight',
+        class => 'shaded',
       },
       ...
     ],
@@ -144,7 +147,6 @@ Usage:
 <P ALIGN="right" CLASS="noprint">
 Download full reports<BR>
 as <A HREF="<% "$myself;_type=xls" %>">Excel spreadsheet</A><BR>
-% # as <A HREF="<% "$myself;_type=csv" %>">CSV file</A> # is this still needed?
 </P>
 <style type="text/css">
 .report * {
@@ -155,9 +157,9 @@ as <A HREF="<% "$myself;_type=xls" %>">Excel spreadsheet</A><BR>
 .report td {
   text-align: right;
 }
-.total * { background-color: #f5f6be; }
-.shaded * { background-color: #c8c8c8; }
-.totalshaded * { background-color: #bfc094; }
+.total { background-color: #f5f6be; }
+.shaded { background-color: #c8c8c8; }
+.totalshaded { background-color: #bfc094; }
 </style>
 <table class="report" width="100%" cellspacing=0>
 % foreach my $rowinfo (@rows) {

commit af4e5e495388889f3b8d3d9bb385064fb4b6d539
Author: Mark Wells <mark at freeside.biz>
Date:   Fri Feb 5 15:16:12 2016 -0800

    refactor and fix customer accounting summary report, #24112 and #40103

diff --git a/httemplate/search/customer_accounting_summary.html b/httemplate/search/customer_accounting_summary.html
index 744b313..a8e5033 100644
--- a/httemplate/search/customer_accounting_summary.html
+++ b/httemplate/search/customer_accounting_summary.html
@@ -1,120 +1,8 @@
-% if ( $cgi->param('_type') =~ /(xls)$/ ) {
-<%perl>
-  # egregious false laziness w/ search/report_tax-xls.cgi
-  my $format = $FS::CurrentUser::CurrentUser->spreadsheet_format;
-  my $filename = $cgi->url(-relative => 1);
-  $filename =~ s/\.html$//;
-  $filename .= $format->{extension};
-  http_header('Content-Type' => $format->{mime_type});
-  http_header('Content-Disposition' => qq!attachment;filename="$filename"!);
-
-  my $output = '';
-  my $XLS = IO::String->new($output);
-  my $workbook = $format->{class}->new($XLS)
-    or die "Error opening .xls file: $!";
-
-  my $worksheet = $workbook->add_worksheet('Summary');
-
-  my %format = (
-    header => {
-      size      => 11,
-      bold      => 1,
-      align     => 'center',
-      valign    => 'vcenter',
-      text_wrap => 1,
-    },
-    money => {
-      size      => 11,
-      align     => 'right',
-      valign    => 'bottom',
-      num_format=> 8,
-    },
-    '' => {},
-  );
-  my %default = (
-      font      => 'Calibri',
-      border    => 1,
-  );
-  foreach (keys %format) {
-    my %f = (%default, %{$format{$_}});
-    $format{$_} = $workbook->add_format(%f);
-    $format{"m_$_"} = $workbook->add_format(%f);
-  }
-
-  my ($r, $c) = (0, 0);
-  for my $row (@rows) {
-    $c = 0;
-    my $thisrow = shift @cells;
-    for my $cell (@$thisrow) {
-      if (!ref($cell)) {
-        # placeholder, so increment $c so that we write to the correct place
-        $c++;
-        next;
-      }
-      # format name
-      my $f = '';
-      $f = 'header' if $row->{header} or $cell->{header};
-      $f = 'money' if $cell->{format} eq 'money';
-      if ( $cell->{rowspan} > 1 or $cell->{colspan} > 1 ) {
-        my $range = xl_range_formula(
-          'Summary',
-          $r, $r - 1 + ($cell->{rowspan} || 1),
-          $c, $c - 1 + ($cell->{colspan} || 1)
-        );
-        #warn "merging $range\n";
-        $worksheet->merge_range($range, $cell->{value}, $format{"m_$f"});
-      } else {
-      #warn "writing ".xl_rowcol_to_cell($r, $c)."\n";
-        $worksheet->write( $r, $c, $cell->{value}, $format{$f} );
-      }
-      $c++;
-    } #$cell
-  $r++;
-  } #$row
-  $workbook->close;
-
-  http_header('Content-Length' => length($output));
-  $m->print($output);
-</%perl>
-% } else {
-<& /elements/header.html, $title &>
-% my $myself = $cgi->self_url;
-<P ALIGN="right" CLASS="noprint">
-Download full reports<BR>
-as <A HREF="<% "$myself;_type=xls" %>">Excel spreadsheet</A><BR>
-% # as <A HREF="<% "$myself;_type=csv" %>">CSV file</A> # is this still needed?
-</P>
-<style type="text/css">
-.report * {
-  background-color: #f8f8f8;
-  border: 1px solid #999999;
-  padding: 2px;
-}
-.report td {
-  text-align: right;
-}
-.total * { background-color: #f5f6be; }
-.shaded * { background-color: #c8c8c8; }
-.totalshaded * { background-color: #bfc094; }
-</style>
-<table class="report" width="100%" cellspacing=0>
-% foreach my $rowinfo (@rows) {
-  <tr<% $rowinfo->{class} ? ' class="'.$rowinfo->{class}.'"' : ''%>>
-%   my $thisrow = shift @cells;
-%   foreach my $cell (@$thisrow) {
-%     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;
-      <<%$td%><%$style%>><% $cell->{value} |h %></<%$td%>>
-%   }
-  </tr>
-% }
-</table>
-
-<& /elements/footer.html &>
-% }
+<& elements/grid-report.html,
+  title => $title,
+  rows  => \@rows,
+  cells => \@cells,
+&>
 <%init>
 
 die "access denied"
@@ -224,17 +112,14 @@ my @cells; # arrayrefs of cell info
 $rows[0] = {};
 $cells[0] = [
   { header => 1, rowspan => 2, colspan => ($setuprecur ? 4 : 3) },
-  ($setuprecur ? '' : ()),
   map {
     { header => 1, colspan => ($grossdiscount ? 3 : 2), value => time2str('%b %Y', $_) },
-    ''
   } @{ $data->{speriod} }
 ];
 my $ncols = scalar(@{ $data->{speriod} });
 
 $rows[1] = {};
-$cells[1] = [ '',
-  ($setuprecur ? '' : ()),
+$cells[1] = [
   map { 
   ( ($grossdiscount 
       ? (
@@ -270,8 +155,6 @@ foreach my $cust_main (@cust_main) { # correspond to cross_params
           rowspan => ($setuprecur ? 2 : 1),
         },
       ;
-    } else {
-      push @thisrow, '';
     }
     if ( $setuprecur ) {
       # subheading
@@ -310,8 +193,6 @@ for my $subrow (0..($setuprecur ? 1 : 0)) {
         header => 1,
         colspan => 3,
         rowspan => ($setuprecur ? 2 : 1), };
-  } else {
-    push @thisrow, '';
   }
   if ( $setuprecur ) {
     push @thisrow,
diff --git a/httemplate/search/elements/grid-report.html b/httemplate/search/elements/grid-report.html
new file mode 100644
index 0000000..cb06b2b
--- /dev/null
+++ b/httemplate/search/elements/grid-report.html
@@ -0,0 +1,187 @@
+<%doc>
+
+Simple display front-end for reports that produce some kind of data table,
+which the user can request as an Excel spreadsheet. /elements/header.html
+and /elements/footer.html are included automatically, so don't include them
+again.
+
+Usage:
+
+<& elements/grid-report.html,
+  title => 'My Report',
+  rows => [
+    { header => 1, },
+    ...
+  ],
+  cells => [
+    [ # row 0
+      { value => '123.45',
+        # optional
+        format => 'money',
+        header => 1,
+        rowspan => 2,
+        colspan => 3,
+        class => 'highlight',
+      },
+      ...
+    ],
+  ],
+  head => q[<div>Thing to insert before the table</div>],
+  foot => q[<span>That's all folks!</span>].
+&>
+</%doc>
+% if ( $cgi->param('_type') =~ /(xls)$/ ) {
+<%perl>
+  # egregious false laziness w/ search/report_tax-xls.cgi
+  # and search/customer_cdr_profit.html
+  my $format = $FS::CurrentUser::CurrentUser->spreadsheet_format;
+  my $filename = $cgi->url(-relative => 1);
+  $filename =~ s/\.html$//;
+  $filename .= $format->{extension};
+  http_header('Content-Type' => $format->{mime_type});
+  http_header('Content-Disposition' => qq!attachment;filename="$filename"!);
+
+  my $output = '';
+  my $XLS = IO::String->new($output);
+  my $workbook = $format->{class}->new($XLS)
+    or die "Error opening .xls file: $!";
+
+  my $worksheet = $workbook->add_worksheet('Summary');
+
+  my %format = (
+    header => {
+      size      => 11,
+      bold      => 1,
+      align     => 'center',
+      valign    => 'vcenter',
+      text_wrap => 1,
+    },
+    money => {
+      size      => 11,
+      align     => 'right',
+      valign    => 'bottom',
+      num_format=> 8,
+    },
+    '' => {},
+  );
+  my %default = (
+      font      => 'Calibri',
+      border    => 1,
+  );
+  foreach (keys %format) {
+    my %f = (%default, %{$format{$_}});
+    $format{$_} = $workbook->add_format(%f);
+    $format{"m_$_"} = $workbook->add_format(%f);
+  }
+
+  my ($r, $c) = (0, 0);
+  # indices in these correspond to column positions
+  my @rowspans;
+  my @widths;
+  
+  for my $row (@rows) {
+    $c = 0;
+    my $thisrow = shift @cells;
+    for my $cell (@$thisrow) {
+      # skip over cells that are occupied by rowspans above them
+      while ($rowspans[$c]) {
+        $rowspans[$c]--;
+        $c++;
+      }
+
+      # skip this cell if it's empty, also
+      next if !ref($cell);
+      # format name
+      my $f = '';
+      $f = 'header' if $row->{header} or $cell->{header};
+      $f = 'money' if $cell->{format} eq 'money';
+      if ( $cell->{rowspan} > 1 or $cell->{colspan} > 1 ) {
+        my $range = xl_range_formula(
+          'Summary',
+          $r, $r - 1 + ($cell->{rowspan} || 1),
+          $c, $c - 1 + ($cell->{colspan} || 1)
+        );
+        #warn "merging $range\n";
+        $worksheet->merge_range($range, $cell->{value}, $format{"m_$f"});
+      } else {
+      #warn "writing ".xl_rowcol_to_cell($r, $c)."\n";
+        $worksheet->write( $r, $c, $cell->{value}, $format{$f} );
+      }
+
+      # estimate column width, as in search-xls, but without date formats
+      my $width = length($cell->{value}) / ($cell->{colspan} || 1);
+      $width *= 1.1 if $f eq 'header';
+      $width++ if $f eq 'money'; # for money symbol
+      $width += 2; # pad it
+
+      for (1 .. ($cell->{colspan} || 1)) {
+        # adjust minimum widths to allow for this cell's contents
+        $widths[$c] = $width if $width > ($widths[$c] || 0);
+
+        # and if this cell has a rowspan, block off that many rows below it
+        if ( $cell->{rowspan} > 1 ) {
+          $rowspans[$c] = $cell->{rowspan} - 1;
+        }
+        $c++;
+      }
+    } #$cell
+  $r++;
+  } #$row
+
+  $c = 0;
+  for my $c (0 .. scalar(@widths) - 1) {
+    $worksheet->set_column($c, $c, $widths[$c]);
+  }
+  $workbook->close;
+
+  http_header('Content-Length' => length($output));
+  $m->print($output);
+</%perl>
+% } else {
+<& /elements/header.html, $title &>
+<% $head %>
+% my $myself = $cgi->self_url;
+<P ALIGN="right" CLASS="noprint">
+Download full reports<BR>
+as <A HREF="<% "$myself;_type=xls" %>">Excel spreadsheet</A><BR>
+% # as <A HREF="<% "$myself;_type=csv" %>">CSV file</A> # is this still needed?
+</P>
+<style type="text/css">
+.report * {
+  background-color: #f8f8f8;
+  border: 1px solid #999999;
+  padding: 2px;
+}
+.report td {
+  text-align: right;
+}
+.total * { background-color: #f5f6be; }
+.shaded * { background-color: #c8c8c8; }
+.totalshaded * { background-color: #bfc094; }
+</style>
+<table class="report" width="100%" cellspacing=0>
+% foreach my $rowinfo (@rows) {
+  <tr<% $rowinfo->{class} ? ' class="'.$rowinfo->{class}.'"' : ''%>>
+%   my $thisrow = shift @cells;
+%   foreach my $cell (@$thisrow) {
+%     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 .= ' class="' . $cell->{class} . '"' if $cell->{class};
+      <<%$td%><%$style%>><% $cell->{value} |h %></<%$td%>>
+%   }
+  </tr>
+% }
+</table>
+<% $foot %>
+<& /elements/footer.html &>
+% }
+<%args>
+$title
+ at rows
+ at cells
+$head => ''
+$foot => ''
+</%args>

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

Summary of changes:
 httemplate/search/customer_accounting_summary.html |  131 +-------------
 httemplate/search/customer_cdr_profit.html         |  137 ++------------
 httemplate/search/elements/grid-report.html        |  189 ++++++++++++++++++++
 3 files changed, 213 insertions(+), 244 deletions(-)
 create mode 100644 httemplate/search/elements/grid-report.html




More information about the freeside-commits mailing list