add Excel and CSV download of templated reports and clean up their HTML formatting...
authorivan <ivan>
Sun, 6 Mar 2005 03:04:29 +0000 (03:04 +0000)
committerivan <ivan>
Sun, 6 Mar 2005 03:04:29 +0000 (03:04 +0000)
29 files changed:
README.1.5.7
htetc/global.asa
htetc/handler.pl
httemplate/docs/install.html
httemplate/docs/upgrade10.html
httemplate/index.html
httemplate/search/cust_bill.html
httemplate/search/cust_bill_event.html
httemplate/search/cust_credit.html
httemplate/search/cust_main-otaker.cgi
httemplate/search/cust_main-payinfo.html
httemplate/search/cust_main-quickpay.html
httemplate/search/cust_main.cgi
httemplate/search/cust_main.html
httemplate/search/cust_pay.cgi
httemplate/search/cust_pay.html
httemplate/search/cust_pkg_report.cgi
httemplate/search/elements/search.html
httemplate/search/reg_code.html
httemplate/search/report_cust_credit.html
httemplate/search/report_cust_pay.html
httemplate/search/report_prepaid_income.html
httemplate/search/report_tax.html
httemplate/search/sqlradius.html
httemplate/search/svc_acct.html
httemplate/search/svc_domain.html
httemplate/search/svc_www.cgi
httemplate/view/cust_bill-pdf.cgi
httemplate/view/cust_bill-ps.cgi

index ff70961..8c10f88 100644 (file)
@@ -104,7 +104,8 @@ dbdef-create username
 create-history-tables username rate rate_detail rate_region rate_prefix reg_code reg_code_pkg
 dbdef-create username
 
-install Javascript::RPC (JavaScript::RPC::Server::CGI)
+install Javascript::RPC (JavaScript::RPC::Server::CGI), Text::CSV_XS and
+Spreadsheet::WriteExcel
 
 afterwords (for installs w/integrated RT):
 make configure-rt
index 482572a..ed26057 100644 (file)
@@ -14,11 +14,14 @@ use Tie::IxHash;
 use HTML::Entities;
 use IO::Handle;
 use IO::File;
+use IO::Scalar;
 use Net::Whois::Raw qw(whois);
 if ( $] < 5.006 ) {
   eval "use Net::Whois::Raw 0.32 qw(whois)";
   die $@ if $@;
 }
+use Text::CSV_XS;
+use Spreadsheet::WriteExcel;
 use Business::CreditCard;
 use String::Approx qw(amatch);
 use Chart::LinesPoints;
index f115104..f41db36 100644 (file)
@@ -97,11 +97,14 @@ sub handler
       use HTML::Entities;
       use IO::Handle;
       use IO::File;
+      use IO::Scalar;
       use Net::Whois::Raw qw(whois);
       if ( $] < 5.006 ) {
         eval "use Net::Whois::Raw 0.32 qw(whois)";
         die $@ if $@;
       }
+      use Text::CSV_XS;
+      use Spreadsheet::WriteExcel;
       use Business::CreditCard;
       use String::Approx qw(amatch);
       use Chart::LinesPoints;
index 1632fb3..4a89ab3 100644 (file)
@@ -62,6 +62,8 @@ Before installing, you need:
       <li><a href="http://search.cpan.org/search?dist=Crypt-PasswdMD5">Crypt::PasswdMD5</a>
       <li><a href="http://search.cpan.org/search?dist=JavaScript-RPC">JavaScript::RPC (JavaScript::RPC::Server::CGI)</a>
       <li><a href="http://search.cpan.org/search?dist=Frontier-RPC">Frontier::RPC</a>
+      <li><a href="http://search.cpan.org/search?dist=Text-CSV_XS">Text::CSV_XS</a>
+      <li><a href="http://search.cpan.org/search?dist=Spreadsheet-WriteExcel">Spreadsheet::WriteExcel</a>
 <!--      <li><a href="http://search.cpan.org/search?dist=Crypt-YAPassGen">Crypt::YAPassGen</a> -->
       <li><a href="http://search.cpan.org/search?dist=ApacheDBI">Apache::DBI</a> <i>(optional but recommended for better webinterface performance)</i>
     </ul>
index 977755b..2f4549d 100644 (file)
@@ -9,7 +9,8 @@ install Net::SSH 0.08
 - In httpd.conf, change <b>AddHandler perl-script .cgi</b> or <b>SetHandler perl-script</b> to <b>AddHandler perl-script .cgi .html</b>
 
 install NetAddr::IP, Chart::Base, Locale::SubCountry, 
-JavaScript::RPC (JavaScript::RPC::Server::CGI) <!-- and Crypt::YAPassGen-->
+JavaScript::RPC (JavaScript::RPC::Server::CGI), Text::CSV_XS and
+Spreadsheet::WriteExcel<!-- and Crypt::YAPassGen-->
 
 INSERT INTO msgcat ( msgnum, msgcode, locale, msg ) VALUES ( 20, 'svc_external-id', 'en_US', 'External ID' );
 INSERT INTO msgcat ( msgnum, msgcode, locale, msg ) VALUES ( 21, 'svc_external-title', 'en_US', 'Title' );
index 2d326b5..b3b1c23 100644 (file)
     <TR><TD>
         <BR><FONT SIZE="+1"><A HREF="edit/cust_main.cgi">New Customer</A></FONT>
         <BR>
-        <BR><FORM ACTION="search/cust_main.cgi" METHOD="POST"><INPUT TYPE="hidden" NAME="custnum_on" VALUE="1">Customer # <INPUT TYPE="text" NAME="custnum_text"><INPUT TYPE="submit" VALUE="Search"> or <A HREF="search/cust_main.cgi?browse=custnum">all customers by customer number</A></FORM>
-        <FORM ACTION="search/cust_main.cgi" METHOD="POST"><INPUT TYPE="hidden" NAME="last_on" VALUE="1">Last name <INPUT TYPE="text" NAME="last_text"><SELECT NAME="last_type"><OPTION SELECTED VALUE="All">(all)</OPTION><OPTION>Fuzzy<OPTION>Substring</OPTION><OPTION>Exact</OPTION></SELECT><INPUT TYPE="submit" VALUE="Search"> or <A HREF="search/cust_main.cgi?browse=last">all customers by last name</A></FORM>
-        <FORM ACTION="search/cust_main.cgi" METHOD="POST"><INPUT TYPE="hidden" NAME="company_on" VALUE="1">Company <INPUT TYPE="text" NAME="company_text"><SELECT NAME="company_type"><OPTION SELECTED VALUE="All">(all)</OPTION><OPTION>Fuzzy<OPTION>Substring</OPTION><OPTION>Exact</OPTION></SELECT><INPUT TYPE="submit" VALUE="Search"> or <A HREF="search/cust_main.cgi?browse=company">all customers by company</A></FORM>
+        <BR><FORM ACTION="search/cust_main.cgi" METHOD="GET"><INPUT TYPE="hidden" NAME="custnum_on" VALUE="1">Customer # <INPUT TYPE="text" NAME="custnum_text"><INPUT TYPE="submit" VALUE="Search"> or <A HREF="search/cust_main.cgi?browse=custnum">all customers by customer number</A></FORM>
+        <FORM ACTION="search/cust_main.cgi" METHOD="GET"><INPUT TYPE="hidden" NAME="last_on" VALUE="1">Last name <INPUT TYPE="text" NAME="last_text"><SELECT NAME="last_type"><OPTION SELECTED VALUE="All">(all)</OPTION><OPTION>Fuzzy<OPTION>Substring</OPTION><OPTION>Exact</OPTION></SELECT><INPUT TYPE="submit" VALUE="Search"> or <A HREF="search/cust_main.cgi?browse=last">all customers by last name</A></FORM>
+        <FORM ACTION="search/cust_main.cgi" METHOD="GET"><INPUT TYPE="hidden" NAME="company_on" VALUE="1">Company <INPUT TYPE="text" NAME="company_text"><SELECT NAME="company_type"><OPTION SELECTED VALUE="All">(all)</OPTION><OPTION>Fuzzy<OPTION>Substring</OPTION><OPTION>Exact</OPTION></SELECT><INPUT TYPE="submit" VALUE="Search"> or <A HREF="search/cust_main.cgi?browse=company">all customers by company</A></FORM>
 <% if ( $conf->exists('address2-search') ) { %>
-        <FORM ACTION="search/cust_main.cgi" METHOD="POST"><INPUT TYPE="hidden" NAME="address2_on" VALUE="1">Unit <INPUT TYPE="text" NAME="address2_text"><INPUT TYPE="submit" VALUE="Search"></FORM>
+        <FORM ACTION="search/cust_main.cgi" METHOD="GET"><INPUT TYPE="hidden" NAME="address2_on" VALUE="1">Unit <INPUT TYPE="text" NAME="address2_text"><INPUT TYPE="submit" VALUE="Search"></FORM>
 <% } %>
-        <FORM ACTION="search/cust_main.cgi" METHOD="POST"><INPUT TYPE="hidden" NAME="phone_on" VALUE="1">Phone # <INPUT TYPE="text" NAME="phone_text"><INPUT TYPE="submit" VALUE="Search"></FORM>
-        <BR><FORM ACTION="search/svc_acct.cgi" METHOD="POST">Username <INPUT TYPE="text" NAME="username"><SELECT NAME="username_type"><OPTION VALUE="All">(all)</OPTION><OPTION>Fuzzy</OPTION><OPTION>Substring</OPTION><OPTION SELECTED>Exact</OPTION></SELECT><INPUT TYPE="submit" VALUE="Search"> or <A HREF="search/svc_acct.cgi?username">all accounts by username</A> or <A HREF="search/svc_acct.cgi?uid">uid</A></FORM>
-        <BR><FORM ACTION="search/svc_domain.cgi" METHOD="POST">Domain <INPUT TYPE="text" NAME="domain"><INPUT TYPE="submit" VALUE="Search"> or <A HREF="search/svc_domain.cgi?domain">all domains</A></FORM>
-       <BR><FORM ACTION="search/svc_broadband.cgi" METHOD="POST">IP Address <INPUT TYPE="text" NAME="ip_addr"><INPUT TYPE="submit" VALUE="Search"> or <A HREF="search/svc_broadband.cgi?svcnum">all services by svcnum</A> or <A HREF="search/svc_broadband.cgi?blocknum">address block</A></FORM>
+        <FORM ACTION="search/cust_main.cgi" METHOD="GET"><INPUT TYPE="hidden" NAME="phone_on" VALUE="1">Phone # <INPUT TYPE="text" NAME="phone_text"><INPUT TYPE="submit" VALUE="Search"></FORM>
+        <BR><FORM ACTION="search/svc_acct.cgi" METHOD="GET">Username <INPUT TYPE="text" NAME="username"><SELECT NAME="username_type"><OPTION VALUE="All">(all)</OPTION><OPTION>Fuzzy</OPTION><OPTION>Substring</OPTION><OPTION SELECTED>Exact</OPTION></SELECT><INPUT TYPE="submit" VALUE="Search"> or <A HREF="search/svc_acct.cgi?username">all accounts by username</A> or <A HREF="search/svc_acct.cgi?uid">uid</A></FORM>
+        <BR><FORM ACTION="search/svc_domain.cgi" METHOD="GET">Domain <INPUT TYPE="text" NAME="domain"><INPUT TYPE="submit" VALUE="Search"> or <A HREF="search/svc_domain.cgi?domain">all domains</A></FORM>
+       <BR><FORM ACTION="search/svc_broadband.cgi" METHOD="GET">IP Address <INPUT TYPE="text" NAME="ip_addr"><INPUT TYPE="submit" VALUE="Search"> or <A HREF="search/svc_broadband.cgi?svcnum">all services by svcnum</A> or <A HREF="search/svc_broadband.cgi?blocknum">address block</A></FORM>
         <BR><A HREF="search/svc_forward.cgi?svcnum">all mail forwards by svcnum</A><BR>
         <BR><A HREF="search/svc_www.cgi?svcnum">all virtual hosts by svcnum</A><BR>
         <BR><A HREF="search/svc_external.cgi?svcnum">all external services by svcnum</A><BR>
     <TR><TD>
       <BR><A HREF="search/cust_main-quickpay.html">Quick payment entry</A>
       <BR>
-      <BR><FORM ACTION="search/cust_main.cgi" METHOD="POST">Credit card # <INPUT TYPE="hidden" NAME="card_on" VALUE="1"><INPUT TYPE="text" NAME="card"><INPUT TYPE="submit" VALUE="Search"></FORM>
-      <FORM ACTION="search/cust_bill.html" METHOD="POST">Invoice # <INPUT TYPE="text" NAME="invnum" SIZE="8"><INPUT TYPE="submit" VALUE="Search"></FORM>
-      <FORM ACTION="search/cust_pay.cgi" METHOD="POST">Check # <INPUT TYPE="text" NAME="payinfo" SIZE="8"><INPUT TYPE="hidden" NAME="payby" VALUE="BILL"><INPUT TYPE="submit" VALUE="Search"></FORM>
+      <BR><FORM ACTION="search/cust_main.cgi" METHOD="GET">Credit card # <INPUT TYPE="hidden" NAME="card_on" VALUE="1"><INPUT TYPE="text" NAME="card"><INPUT TYPE="submit" VALUE="Search"></FORM>
+      <FORM ACTION="search/cust_bill.html" METHOD="GET">Invoice # <INPUT TYPE="text" NAME="invnum" SIZE="8"><INPUT TYPE="submit" VALUE="Search"></FORM>
+      <FORM ACTION="search/cust_pay.cgi" METHOD="GET">Check # <INPUT TYPE="text" NAME="payinfo" SIZE="8"><INPUT TYPE="hidden" NAME="payby" VALUE="BILL"><INPUT TYPE="submit" VALUE="Search"></FORM>
       <BR><A HREF="browse/cust_pay_batch.cgi">View pending credit card batch</A>      <BR><BR><A HREF="search/cust_pkg_report.cgi">Packages (by next bill date range)</A>
       <BR><BR>Invoice reports
             <UL>
       <UL>
         <LI><A HREF="search/cust_main-otaker.cgi">Search customers by ordering employee</A>
       </UL>
-    <FORM ACTION="search/sql.html" METHOD="POST">SQL query: <TT>SELECT </TT><INPUT TYPE="text" NAME="sql" SIZE=32><INPUT TYPE="submit" VALUE="Query"></FORM>
+    <FORM ACTION="search/sql.html" METHOD="GET">SQL query: <TT>SELECT </TT><INPUT TYPE="text" NAME="sql" SIZE=32><INPUT TYPE="submit" VALUE="Query"></FORM>
 
     <BR>
     </TD></TR>
index 3ae624a..440e468 100755 (executable)
        : '';
    };
 
-%>
-<%= include( 'elements/search.html',
-               'title'       => 'Invoice Search Results',
-               'name'        => 'invoices',
-               'query'       => $sql_query,
-               'count_query' => $count_query,
-               'count_addl'  => [ '$%.2f total invoiced',
-                                  '$%.2f total outstanding balance',
-                                ],
-               'redirect'    => $link,
-               'header'      =>
-                 [ 'Invoice #', qw(Balance Amount Date), 'Contact name',
-                   'Company' ],
-               'fields'      => [
-                 'invnum',
-                 sub { sprintf('$%.2f', shift->get('owed') ) },
-                 sub { sprintf('$%.2f', shift->charged     ) },
-                 sub { time2str('%b %d %Y', shift->_date ) },
-                 sub { my $cust_bill = shift;
-                       my $cust_main = $cust_bill->cust_main;
-                       $cust_main
-                         ? $cust_main->get('last'). ', '. $cust_main->first
-                         : "WARNING: can't find cust_main.custnum ".
-                           $cust_bill->custnum. ' (cust_bill.invnum '.
-                           $cust_bill->invnum. ')';
-                     },
-                 sub { my $cust_main = shift->cust_main;
-                       $cust_main ? $cust_main->company : '';
-                     },
-               ],
-               'links' => [
-                 $link,
-                 $link,
-                 $link,
-                 $link,
-                 $clink,
-                 $clink,
-               ],
-
-    )
+%><%= include( 'elements/search.html',
+                 'title'       => 'Invoice Search Results',
+                 'name'        => 'invoices',
+                 'query'       => $sql_query,
+                 'count_query' => $count_query,
+                 'count_addl'  => [ '$%.2f total invoiced',
+                                    '$%.2f total outstanding balance',
+                                  ],
+                 'redirect'    => $link,
+                 'header'      =>
+                   [ 'Invoice #', qw(Balance Amount Date), 'Contact name',
+                     'Company' ],
+                 'fields'      => [
+                   'invnum',
+                   sub { sprintf('$%.2f', shift->get('owed') ) },
+                   sub { sprintf('$%.2f', shift->charged     ) },
+                   sub { time2str('%b %d %Y', shift->_date ) },
+                   sub { my $cust_bill = shift;
+                         my $cust_main = $cust_bill->cust_main;
+                         $cust_main
+                           ? $cust_main->get('last'). ', '. $cust_main->first
+                           : "WARNING: can't find cust_main.custnum ".
+                             $cust_bill->custnum. ' (cust_bill.invnum '.
+                             $cust_bill->invnum. ')';
+                       },
+                   sub { my $cust_main = shift->cust_main;
+                         $cust_main ? $cust_main->company : '';
+                       },
+                 ],
+                 'links' => [
+                   $link,
+                   $link,
+                   $link,
+                   $link,
+                   $clink,
+                   $clink,
+                 ],
+  
+      )
 %>
index cd96ddf..6de2709 100755 (executable)
@@ -8,7 +8,7 @@
   </HEAD>
   <BODY BGCOLOR="#e8e8e8">
     <H1>Invoice event errors</H1>
-    <FORM ACTION="cust_bill_event.cgi" METHOD="post">
+    <FORM ACTION="cust_bill_event.cgi" METHOD="GET">
     <TABLE>
       <!--<TR>
         <TD ALIGN="right">Customer type</TD>
index 8f6258e..b978e62 100755 (executable)
 
    my $clink = [ "${p}view/cust_main.cgi?", 'custnum' ];
 
-%>
-<%= include( 'elements/search.html',
-               'title'       => $title,
-               'name'        => 'credits',
-               'query'       => $sql_query,
-               'count_query' => $count_query,
-               'count_addl'  => [ '$%.2f total credited', ],
-               #'redirect'    => $link,
-               'header'      =>
-                 [ qw(Amount Date), 'Cust #', 'Contact name',
-                   qw(Company By Reason) ],
-               'fields'      => [
-                 #'crednum',
-                 sub { sprintf('$%.2f', shift->amount ) },
-                 sub { time2str('%b %d %Y', shift->_date ) },
-                 'custnum',
-                 sub { $_[0]->get('last'). ', '. $_[0]->first; },
-                 'company',
-                 'otaker',
-                 'reason',
-               ],
-               'align' => 'rrrllll',
-               'links' => [
-                 '',
-                 '',
-                 $clink,
-                 $clink,
-                 $clink,
-                 '',
-                 '',
-               ],
-    )
+%><%= include( 'elements/search.html',
+                 'title'       => $title,
+                 'name'        => 'credits',
+                 'query'       => $sql_query,
+                 'count_query' => $count_query,
+                 'count_addl'  => [ '$%.2f total credited', ],
+                 #'redirect'    => $link,
+                 'header'      =>
+                   [ qw(Amount Date), 'Cust #', 'Contact name',
+                     qw(Company By Reason) ],
+                 'fields'      => [
+                   #'crednum',
+                   sub { sprintf('$%.2f', shift->amount ) },
+                   sub { time2str('%b %d %Y', shift->_date ) },
+                   'custnum',
+                   sub { $_[0]->get('last'). ', '. $_[0]->first; },
+                   'company',
+                   'otaker',
+                   'reason',
+                 ],
+                 'align' => 'rrrllll',
+                 'links' => [
+                   '',
+                   '',
+                   $clink,
+                   $clink,
+                   $clink,
+                   '',
+                   '',
+                 ],
+      )
 %>
index 4421436..03c2619 100755 (executable)
@@ -7,7 +7,7 @@
       Customer Search
     </FONT>
     <BR>
-    <FORM ACTION="cust_main.cgi" METHOD="post">
+    <FORM ACTION="cust_main.cgi" METHOD="GET">
       Search for <B>Order taker</B>: 
       <INPUT TYPE="hidden" NAME="otaker_on" VALUE="TRUE">
       <% my $sth = dbh->prepare("SELECT DISTINCT otaker FROM cust_main")
index 671b5ef..b82b610 100755 (executable)
@@ -7,7 +7,7 @@
       Customer Search
     </FONT>
     <BR>
-    <FORM ACTION="cust_main.cgi" METHOD="post">
+    <FORM ACTION="cust_main.cgi" METHOD="GET">
       Search for <B>Credit card #</B>: 
       <INPUT TYPE="hidden" NAME="card_on" VALUE="TRUE">
       <INPUT TYPE="text" NAME="card">
index 077d290..154a641 100755 (executable)
@@ -8,7 +8,7 @@
     </FONT>
     <BR><BR>
     <A HREF="../">Main Menu</A><BR><BR>
-    <FORM ACTION="cust_main.cgi" METHOD="post">
+    <FORM ACTION="cust_main.cgi" METHOD="GET">
       <INPUT TYPE="hidden" NAME="quickpay" VALUE="yes">
       <INPUT TYPE="checkbox" NAME="last_on" CHECKED> Search for <B>last name</B>: 
       <INPUT TYPE="text" NAME="last_text">
index ecff4bf..a325667 100755 (executable)
@@ -285,7 +285,7 @@ if ( scalar(@cust_main) == 1 && ! $cgi->param('referral_custnum') ) {
       or eidiot "Illegal referral_custnum\n";
     my $referral_custnum = $1;
     my $cust_main = qsearchs('cust_main', { custnum => $referral_custnum } );
-    print '<FORM METHOD=POST>'.
+    print '<FORM METHOD="GET">'.
           qq!<INPUT TYPE="hidden" NAME="referral_custnum" VALUE="$referral_custnum">!.
           'referrals of <A HREF="'. popurl(2).
           "view/cust_main.cgi?$referral_custnum\">$referral_custnum: ".
index 5a066e4..4f75084 100755 (executable)
@@ -7,7 +7,7 @@
       Customer Search
     </FONT>
     <BR><BR>
-    <FORM ACTION="cust_main.cgi" METHOD="post">
+    <FORM ACTION="cust_main.cgi" METHOD="GET">
       <INPUT TYPE="checkbox" NAME="last_on" CHECKED> Search for <B>last name</B>: 
       <INPUT TYPE="text" NAME="last_text">
       using search method: <SELECT NAME="last_type">
index d4aaaa8..01a2ed9 100755 (executable)
 
    my $link = [ "${p}view/cust_main.cgi?", 'custnum' ];
 
-%>
-<%= include( 'elements/search.html',
-               'title'       => $title,
-               'name'        => 'payments',
-               'query'       => $sql_query,
-               'count_query' => $count_query,
-               'count_addl'  => [ '$%.2f total paid', ],
-               'header'      =>
-                 [ qw(Payment Amount Date), 'Cust #', 'Contact name',
-                   'Company', ],
-               'fields'      => [
-                 sub {
-                   my $cust_pay = shift;
-                   if ( $cust_pay->payby eq 'CARD' ) {
-                     'Card #'. $cust_pay->payinfo_masked;
-                   } elsif ( $cust_pay->payby eq 'CHEK' ) {
-                     'E-check acct#'. $cust_pay->payinfo;
-                   } elsif ( $cust_pay->payby eq 'BILL' ) {
-                     'Check #'. $cust_pay->payinfo;
-                   } else {
-                     $cust_pay->payby. ' '. $cust_pay->payinfo;
-                   }
-                 },
-                 sub { sprintf('$%.2f', shift->paid ) },
-                 sub { time2str('%b %d %Y', shift->_date ) },
-                 'custnum',
-                 sub { $_[0]->get('last'). ', '. $_[0]->first; },
-                 'company',
-               ],
-               'align' => 'lrrrll',
-               'links' => [
-                 '',
-                 '',
-                 '',
-                 $link,
-                 $link,
-                 $link,
-               ],
-    )
+%><%= include( 'elements/search.html',
+                 'title'       => $title,
+                 'name'        => 'payments',
+                 'query'       => $sql_query,
+                 'count_query' => $count_query,
+                 'count_addl'  => [ '$%.2f total paid', ],
+                 'header'      =>
+                   [ qw(Payment Amount Date), 'Cust #', 'Contact name',
+                     'Company', ],
+                 'fields'      => [
+                   sub {
+                     my $cust_pay = shift;
+                     if ( $cust_pay->payby eq 'CARD' ) {
+                       'Card #'. $cust_pay->payinfo_masked;
+                     } elsif ( $cust_pay->payby eq 'CHEK' ) {
+                       'E-check acct#'. $cust_pay->payinfo;
+                     } elsif ( $cust_pay->payby eq 'BILL' ) {
+                       'Check #'. $cust_pay->payinfo;
+                     } else {
+                       $cust_pay->payby. ' '. $cust_pay->payinfo;
+                     }
+                   },
+                   sub { sprintf('$%.2f', shift->paid ) },
+                   sub { time2str('%b %d %Y', shift->_date ) },
+                   'custnum',
+                   sub { $_[0]->get('last'). ', '. $_[0]->first; },
+                   'company',
+                 ],
+                 'align' => 'lrrrll',
+                 'links' => [
+                   '',
+                   '',
+                   '',
+                   $link,
+                   $link,
+                   $link,
+                 ],
+      )
 %>
index 3848d66..6414cf7 100755 (executable)
@@ -7,7 +7,7 @@
       Check # Search
     </FONT>
     <BR><BR>
-    <FORM ACTION="cust_pay.cgi" METHOD="post">
+    <FORM ACTION="cust_pay.cgi" METHOD="GET">
       Search for <B>check #</B>:
       <INPUT TYPE="text" NAME="payinfo">
       <INPUT TYPE="hidden" NAME="payby" VALUE="BILL">
index b316745..6bd9189 100755 (executable)
@@ -8,7 +8,7 @@
   </HEAD>
   <BODY BGCOLOR="#e8e8e8">
     <H1>Packages</H1>
-    <FORM ACTION="cust_pkg.cgi" METHOD="post">
+    <FORM ACTION="cust_pkg.cgi" METHOD="GET">
     <INPUT TYPE="hidden" NAME="magic" VALUE="bill">
       Return packages with next bill date:<BR><BR>
       <TABLE>
index 712d63a..85e5af2 100644 (file)
@@ -1,6 +1,7 @@
 <%
 
   my(%opt) = @_;
+  #warn join(' / ', map { "$_ => $opt{$_}" } keys %opt ). "\n";
 
   my %align = (
     'l' => 'left',
   $opt{align} = [ map $align{$_}, split(//, $opt{align}) ],
     unless !$opt{align} || ref($opt{align});
 
-  #if ( ref($opt{'query'}) ) {
-  #
-  #}
+  my $type = '';
+  my $limit = '';
+  my($maxrecords, $total, $offset, $count_arrayref);
 
-  unless (exists($opt{'count_query'}) && length($opt{'count_query'})) {
-    ( $opt{'count_query'} = $opt{'query'} ) =~
-      s/^\s*SELECT\s*(.*?)\s+FROM\s/SELECT COUNT(*) FROM /i;
-  }
+  if ( $cgi->param('_type') =~ /^(csv|\w*\.xls)$/ ) {
+  
+    $type = $1;
 
-  my $conf = new FS::Conf;
-  my $maxrecords = $conf->config('maxsearchrecordsperpage');
+  } else { #setup some pagination things if we're in html mode
 
-  my $limit = $maxrecords ? "LIMIT $maxrecords" : '';
+    unless (exists($opt{'count_query'}) && length($opt{'count_query'})) {
+      ( $opt{'count_query'} = $opt{'query'} ) =~
+        s/^\s*SELECT\s*(.*?)\s+FROM\s/SELECT COUNT(*) FROM /i;
+    }
 
-  my $offset = $cgi->param('offset') || 0;
-  $limit .= " OFFSET $offset" if $offset;
+    my $conf = new FS::Conf;
+    $maxrecords = $conf->config('maxsearchrecordsperpage');
 
-  my $count_sth = dbh->prepare($opt{'count_query'})
-    or die "Error preparing $opt{'count_query'}: ". dbh->errstr;
-  $count_sth->execute
-    or die "Error executing $opt{'count_query'}: ". $count_sth->errstr;
-  my $count_arrayref = $count_sth->fetchrow_arrayref;
-  my $total = $count_arrayref->[0];
+    $limit = $maxrecords ? "LIMIT $maxrecords" : '';
 
-  #warn join(' / ', map { "$_ => $opt{$_}" } keys %opt ). "\n";
+    $offset = $cgi->param('offset') || 0;
+    $limit .= " OFFSET $offset" if $offset;
+
+    my $count_sth = dbh->prepare($opt{'count_query'})
+      or die "Error preparing $opt{'count_query'}: ". dbh->errstr;
+    $count_sth->execute
+      or die "Error executing $opt{'count_query'}: ". $count_sth->errstr;
+    $count_arrayref = $count_sth->fetchrow_arrayref;
+    $total = $count_arrayref->[0];
+
+  }
+
+  # run the query
 
   my $header = $opt{'header'};
   my $rows;
     $header ||= $sth->{NAME};
   }
 
-  if ( exists($opt{'redirect'}) && scalar(@$rows) == 1 && $total == 1 ) {
-    my( $url, $method ) = @{$opt{'redirect'}};
-    redirect( $url. $rows->[0]->$method() );
-  } else {
-    $opt{'name'} =~ s/s$// if $total == 1;
-%>
-<%= include( '/elements/header.html', $opt{'title'},
-               include( '/elements/menubar.html', 'Main menu' => $p )
-           )
-%>
-<% my $pager = include ( '/elements/pager.html',
-                           'offset'     => $offset,
-                           'num_rows'   => scalar(@$rows),
-                           'total'      => $total,
-                           'maxrecords' => $maxrecords,
-                       );
-%>
-<% unless ( $total ) { %>
-  No matching <%= $opt{'name'} %> found.<BR>
-<% } else { %>
-  <%= $total %> total <%= $opt{'name'} %><BR>
-  <% if ( $opt{'count_addl'} ) { %>
-    <% my $n=0; foreach my $count ( @{$opt{'count_addl'}} ) { %>
-      <%= sprintf( $count, $count_arrayref->[++$n] ) %><BR>
-    <% } %>
-  <% } %>
-  <BR><%= $pager %>
-  <%= include( '/elements/table.html' ) %>
-    <TR>
-    <% foreach my $header ( @$header ) { %>
-         <TH><%= $header %></TH>
-    <% } %>
-    </TR>
-    <% foreach my $row ( @$rows ) { %>
-         <TR>
-         <% if ( $opt{'fields'} ) {
-              my $links = $opt{'links'} ? [ @{$opt{'links'}} ] : '';
-              my $aligns = $opt{'align'} ? [ @{$opt{'align'}} ] : '';
-              foreach my $field ( @{$opt{'fields'}} ) {
-                my $align = $aligns ? shift @$aligns : '';
-                $align = " ALIGN=$align" if $align;
-                my $a = '';
-                if ( $links ) {
-                  my $link = shift @$links;
-                  $link = &{$link}($row) if ref($link) eq 'CODE';
-                  if ( $link ) {
-                    my( $url, $method ) = @{$link};
-                    if ( ref($method) eq 'CODE' ) {
-                      $a = $url. &{$method}($row);
-                    } else {
-                      $a = $url. $row->$method();
-                    }
-                    $a = qq(<A HREF="$a">);
-                  }
-                }
-             %>
-             <% if ( ref($field) eq 'CODE' ) { %>
-               <TD<%= $align %>><%= $a %><%= &{$field}($row) %><%= $a ? '</A>' : '' %></TD>
-             <% } else { %>
-               <TD<%= $align %>><%= $a %><%= $row->$field() %><%= $a ? '</A>' : '' %></TD>
-             <% } %>
-           <% } %>
-         <% } else { %>
-           <% foreach ( @$row ) { %>
-                <TD><%= $_ %></TD>
-           <% } %>
-         <% } %>
-         </TR>
-    <% } %>
+  if ( $type eq 'csv' ) {
+
+    #http_header('Content-Type' => 'text/comma-separated-values' ); #IE chokes
+    http_header('Content-Type' => 'text/plain' );
+
+    my $csv = new Text::CSV_XS { 'always_quote' => 1,
+                                 #'eol'          => "\015\012", #"\012"
+                               };
+
+    $csv->combine(@$header); #or die $csv->status;
+    %><%= $csv->string %><%
+
+    foreach my $row ( @$rows ) {
+
+      if ( $opt{'fields'} ) {
+
+        my @line = ();
+
+        foreach my $field ( @{$opt{'fields'}} ) {
+          if ( ref($field) eq 'CODE' ) {
+            push @line, &{$field}($row);
+          } else {
+            push @line, $row->$field();
+          }
+        }
+
+        $csv->combine(@line); #or die $csv->status;
+
+      } else {
+        $csv->combine(@$row); #or die $csv->status;
+      }
+
+      %><%= $csv->string %><%
+
+    }
+
+  #} elsif ( $type eq 'excel' ) {
+  } elsif ( $type =~ /\.xls$/ ) {
+
+    #http_header('Content-Type' => 'application/excel' ); #eww
+    http_header('Content-Type' => 'application/vnd.ms-excel' ); #alas
+    #http_header('Content-Type' => 'application/msexcel' ); #alas
+
+    my $data = '';
+    my $XLS = new IO::Scalar \$data;
+    my $workbook = Spreadsheet::WriteExcel->new($XLS)
+      or die "Error opening .xls file: $!";
+
+    my $worksheet = $workbook->add_worksheet(substr($opt{'title'},0,31));
+
+    my($r,$c) = (0,0);
+
+    $worksheet->write($r, $c++, $_) foreach @$header;
+
+    foreach my $row ( @$rows ) {
+      $r++;
+      $c = 0;
+
+      if ( $opt{'fields'} ) {
+
+        #my $links = $opt{'links'} ? [ @{$opt{'links'}} ] : '';
+        #my $aligns = $opt{'align'} ? [ @{$opt{'align'}} ] : '';
+
+        foreach my $field ( @{$opt{'fields'}} ) {
+          #my $align = $aligns ? shift @$aligns : '';
+          #$align = " ALIGN=$align" if $align;
+          #my $a = '';
+          #if ( $links ) {
+          #  my $link = shift @$links;
+          #  $link = &{$link}($row) if ref($link) eq 'CODE';
+          #  if ( $link ) {
+          #    my( $url, $method ) = @{$link};
+          #    if ( ref($method) eq 'CODE' ) {
+          #      $a = $url. &{$method}($row);
+          #    } else {
+          #      $a = $url. $row->$method();
+          #    }
+          #    $a = qq(<A HREF="$a">);
+          #  }
+          #}
+          if ( ref($field) eq 'CODE' ) {
+            $worksheet->write($r, $c++, &{$field}($row) );
+          } else {
+            $worksheet->write($r, $c++, $row->$field() );
+          }
+        }
+
+      } else {
+        $worksheet->write($r, $c++, $_) foreach @$row;
+      }
+
+    }
+
+    $workbook->close();# or die "Error creating .xls file: $!";
+
+    http_header('Content-Length' => length($data) );
+    %><%= $data %><%
+
+  } else { # regular HTML
+
+    if ( exists($opt{'redirect'}) && scalar(@$rows) == 1 && $total == 1 ) {
+      my( $url, $method ) = @{$opt{'redirect'}};
+      redirect( $url. $rows->[0]->$method() );
+    } else {
+      ( my $xlsname = $opt{'name'} ) =~ s/\W//g;
+      $opt{'name'} =~ s/s$// if $total == 1;
+  %>
+  <%= include( '/elements/header.html', $opt{'title'},
+                 include( '/elements/menubar.html', 'Main menu' => $p )
+             )
+  %>
+  <% my $pager = include ( '/elements/pager.html',
+                             'offset'     => $offset,
+                             'num_rows'   => scalar(@$rows),
+                             'total'      => $total,
+                             'maxrecords' => $maxrecords,
+                         );
+  %>
+  <% unless ( $total ) { %>
+    No matching <%= $opt{'name'} %> found.<BR>
+  <% } else { %>
   
-  </TABLE>
-  <%= $pager %>
-<% } %>
-</BODY>
-</HTML>
+    <TABLE>
+      <TR>
+        <TD>
+          <%= $total %> total <%= $opt{'name'} %><BR>
+          <% if ( $opt{'count_addl'} ) { %>
+            <% my $n=0; foreach my $count ( @{$opt{'count_addl'}} ) { %>
+              <%= sprintf( $count, $count_arrayref->[++$n] ) %><BR>
+            <% } %>
+          <% } %>
+        </TD>
+        <TD ALIGN="right">
+          <% $cgi->param('_type', "$xlsname.xls" ); %>
+          Download full results<BR>
+          as <A HREF="<%= $cgi->self_url %>">Excel spreadsheet</A>
+          <BR>
+          <% $cgi->param('_type', 'csv'); %>
+          as <A HREF="<%= $cgi->self_url %>">CSV file</A>
+        </TD>
+      </TR>
+      <TR>
+        <TD COLSPAN=2>
+  
+            <%= $pager %>
+            <STYLE TYPE="text/css">
+            .grid table { border: solid; empty-cells: show }
+            .grid TH { padding-left: 1px; padding-right: 1px; border: 1px solid #dddddd; border-bottom: dashed 1px black; border-right: none }
+            .grid TD { padding-left: 1px; padding-right: 1px; empty-cells: show; border: 1px solid #cccccc; border-bottom: none; border-right: none }
+            </STYLE>
+            <TABLE CLASS="grid" CELLSPACING=0 CELLPADDING=0 BORDER=1 BORDERCOLOR="#000000" STYLE="border: solid 1px black; empty-cells: show">
+              <TR>
+              <% foreach my $header ( @$header ) { %>
+                   <TH CLASS="grid" BGCOLOR="#cccccc"><%= $header %></TH>
+              <% } %>
+              </TR>
+              <% my $bgcolor1 = '#eeeeee';
+                 my $bgcolor2 = '#ffffff';
+                 my $bgcolor;
+                 foreach my $row ( @$rows ) {
+                   if ( $bgcolor eq $bgcolor1 ) {
+                     $bgcolor = $bgcolor2;
+                   } else {
+                     $bgcolor = $bgcolor1;
+                   }
+              %>
+                   <TR>
+                   <% if ( $opt{'fields'} ) {
+                        my $links = $opt{'links'} ? [ @{$opt{'links'}} ] : '';
+                        my $aligns = $opt{'align'} ? [ @{$opt{'align'}} ] : '';
+                        foreach my $field ( @{$opt{'fields'}} ) {
+                          my $align = $aligns ? shift @$aligns : '';
+                          $align = " ALIGN=$align" if $align;
+                          my $a = '';
+                          if ( $links ) {
+                            my $link = shift @$links;
+                            $link = &{$link}($row) if ref($link) eq 'CODE';
+                            if ( $link ) {
+                              my( $url, $method ) = @{$link};
+                              if ( ref($method) eq 'CODE' ) {
+                                $a = $url. &{$method}($row);
+                              } else {
+                                $a = $url. $row->$method();
+                              }
+                              $a = qq(<A HREF="$a">);
+                            }
+                          }
+                       %>
+                       <% if ( ref($field) eq 'CODE' ) { %>
+                         <TD CLASS="grid" BGCOLOR="<%= $bgcolor %>"<%= $align %>><%= $a %><%= &{$field}($row) %><%= $a ? '</A>' : '' %></TD>
+                       <% } else { %>
+                         <TD CLASS="grid" BGCOLOR="<%= $bgcolor %>"<%= $align %>><%= $a %><%= $row->$field() %><%= $a ? '</A>' : '' %></TD>
+                       <% } %>
+                     <% } %>
+                   <% } else { %>
+                     <% foreach ( @$row ) { %>
+                          <TD CLASS="grid" BGCOLOR="$bgcolor"><%= $_ %></TD>
+                     <% } %>
+                   <% } %>
+                   </TR>
+              <% } %>
+            
+            </TABLE>
+            <%= $pager %>
+  
+          </TD>
+        </TR>
+      </TABLE>
+  
+  <% } %>
+  </BODY>
+  </HTML>
+  <% } %>
 <% } %>
-
index ba1eee0..52a99ff 100644 (file)
@@ -7,29 +7,30 @@ my $agent = qsearchs('agent', { 'agentnum' => $agentnum } );
 
 my $count_query = "SELECT COUNT(*) FROM reg_code WHERE agentnum = $agentnum";
 
-%>
-<%= include( 'elements/search.html',
-               'title'       => 'Unused Registration Codes for '. $agent->agent,
-               'name'        => 'registration codes',
-               'query'       => {  'table'   => 'reg_code',
-                                   'hashref' => { 'agentnum' => $agentnum, },
-                                },
-               'count_query' => $count_query,
-               #'redirect'    => $link,
-               'header'      => [ qw(Code Packages) ],
-               'fields'      => [
-                 'code',
-                 sub { map { 
-                         qq!<A HREF="${p}edit/part_pkg.cgi?!. $_->pkgpart. '">'.
-                         $_->pkg. ' - '. $_->comment.
-                         '</A><BR>'
-                       } $_[0]->part_pkg
-                     },
-               ],
-               'links' => [
-                 '',
-                 #$plink,
-                 '',
-               ],
-    )
+%><%= include( 'elements/search.html',
+                 'title'       => 'Unused Registration Codes for '.
+                                  $agent->agent,
+                 'name'        => 'registration codes',
+                 'query'       => {  'table'   => 'reg_code',
+                                     'hashref' => { 'agentnum' => $agentnum, },
+                                  },
+                 'count_query' => $count_query,
+                 #'redirect'    => $link,
+                 'header'      => [ qw(Code Packages) ],
+                 'fields'      => [
+                   'code',
+                   sub {
+                     map { 
+                       qq!<A HREF="${p}edit/part_pkg.cgi?!. $_->pkgpart. '">'.
+                       $_->pkg. ' - '. $_->comment.
+                       '</A><BR>'
+                     } $_[0]->part_pkg
+                   },
+                 ],
+                 'links' => [
+                   '',
+                   #$plink,
+                   '',
+                 ],
+      )
 %>
index b614e87..3a14f44 100644 (file)
@@ -8,7 +8,7 @@
   </HEAD>
   <BODY BGCOLOR="#e8e8e8">
     <H1>Credit report criteria</H1>
-    <FORM ACTION="cust_credit.html" METHOD="post">
+    <FORM ACTION="cust_credit.html" METHOD="GET">
     <INPUT TYPE="hidden" NAME="magic" VALUE="_date">
     <TABLE>
       <TR>
index d1d4cb9..8b9e273 100644 (file)
@@ -8,7 +8,7 @@
   </HEAD>
   <BODY BGCOLOR="#e8e8e8">
     <H1>Payment report criteria</H1>
-    <FORM ACTION="cust_pay.cgi" METHOD="post">
+    <FORM ACTION="cust_pay.cgi" METHOD="GET">
     <INPUT TYPE="hidden" NAME="magic" VALUE="_date">
     <TABLE>
       <TR>
index e8b6ac4..57c318e 100644 (file)
@@ -8,7 +8,7 @@
   </HEAD>
   <BODY BGCOLOR="#e8e8e8">
     <H1>Prepaid Income (Unearned Revenue) Report</H1>
-    <FORM ACTION="report_prepaid_income.cgi" METHOD="post">
+    <FORM ACTION="report_prepaid_income.cgi" METHOD="GET">
     <TABLE>
       <TR>
         <TD>Prepaid income (unearned revenue) as of </TD>
index d217e56..85af212 100755 (executable)
@@ -7,7 +7,7 @@
     <SCRIPT TYPE="text/javascript" SRC="../elements/calendar-setup.js"></SCRIPT>  </HEAD>
   <BODY BGCOLOR="#e8e8e8">
     <H1>Tax Report Criteria</H1>
-    <FORM ACTION="report_tax.cgi" METHOD="post">
+    <FORM ACTION="report_tax.cgi" METHOD="GET">
       Return <B>tax report</B> for period:
     <TABLE>
       <TR>
index 20e8fb8..8f4878d 100644 (file)
@@ -4,7 +4,7 @@
 <SCRIPT TYPE="text/javascript" SRC="../elements/calendar-en.js"></SCRIPT>
 <SCRIPT TYPE="text/javascript" SRC="../elements/calendar-setup.js"></SCRIPT>
 ') %>
-<FORM NAME="OneTrueForm" ACTION="sqlradius.cgi" METHOD="POST">
+<FORM NAME="OneTrueForm" ACTION="sqlradius.cgi" METHOD="GET">
 <% #include( '/elements/table.html' ) %>
 <%= ntable('#cccccc') %>
 <TR>
index 7423605..c504c2f 100755 (executable)
@@ -7,7 +7,7 @@
       Account Search
     </FONT>
     <BR><BR>
-    <FORM ACTION="svc_acct.cgi" METHOD="post">
+    <FORM ACTION="svc_acct.cgi" METHOD="GET">
       Search for <B>username</B>: 
       <INPUT TYPE="text" NAME="username">
 
index 94bb9a6..b759102 100755 (executable)
@@ -7,7 +7,7 @@
       Domain Search
     </FONT>
     <BR><BR>
-    <FORM ACTION="svc_domain.cgi" METHOD="post">
+    <FORM ACTION="svc_domain.cgi" METHOD="GET">
       Search for <B>domain</B>: 
       <INPUT TYPE="text" NAME="domain">
 
index 1f05c23..1416619 100755 (executable)
@@ -23,20 +23,19 @@ my $link  = [ "${p}view/svc_www.cgi?", 'svcnum', ];
 my $ulink = [ "${p}view/svc_acct.cgi?", 'usersvc', ];
 
 
-%>
-<%= include( 'elements/search.html',
-               'title'       => 'Virtual Host Search Results',
-               'name'        => 'virtual hosts',
-               'query'       => $sql_query,
-               'count_query' => $count_query,
-               'header'      => [ '#', 'Zone', 'User', ],
-               'fields'      => [ 'svcnum',
-                                  sub { $_[0]->domain_record->zone },
-                                  sub { $_[0]->svc_acct->email },
-                                ],
-               'links'       => [ $link,
-                                  '',
-                                  $ulink,
-                                ],
-           )
+%><%= include( 'elements/search.html',
+                 'title'       => 'Virtual Host Search Results',
+                 'name'        => 'virtual hosts',
+                 'query'       => $sql_query,
+                 'count_query' => $count_query,
+                 'header'      => [ '#', 'Zone', 'User', ],
+                 'fields'      => [ 'svcnum',
+                                    sub { $_[0]->domain_record->zone },
+                                    sub { $_[0]->svc_acct->email },
+                                  ],
+                 'links'       => [ $link,
+                                    '',
+                                    $ulink,
+                                  ],
+             )
 %>
index a72a605..ce7ab0c 100755 (executable)
@@ -14,5 +14,4 @@ my $pdf = $cust_bill->print_pdf( '', $templatename);
 http_header('Content-Type' => 'application/pdf' );
 http_header('Content-Length' => length($pdf) );
 http_header('Cache-control' => 'max-age=60' );
-%>
-<%= $pdf %>
+%><%= $pdf %>
index 8485a15..e730a82 100755 (executable)
@@ -10,5 +10,4 @@ my $cust_bill = qsearchs('cust_bill',{'invnum'=>$invnum});
 die "Invoice #$invnum not found!" unless $cust_bill;
 
 http_header('Content-Type' => 'application/postscript' );
-%>
-<%= $cust_bill->print_ps( '', $templatename) %>
+%><%= $cust_bill->print_ps( '', $templatename) %>