Merge branch 'master' of ssh://git.freeside.biz/home/git/freeside
authorChristopher Burger <burgerc@freeside.biz>
Mon, 26 Feb 2018 17:00:45 +0000 (12:00 -0500)
committerChristopher Burger <burgerc@freeside.biz>
Mon, 26 Feb 2018 17:00:45 +0000 (12:00 -0500)
14 files changed:
FS/FS/ClientAPI/MyAccount.pm
FS/FS/cust_pkg.pm
httemplate/edit/process/change-cust_pkg.html
httemplate/elements/create_uri_query
httemplate/elements/email-link.html
httemplate/elements/handle_uri_query
httemplate/misc/email-customers.html
httemplate/search/cust_bill_pkg_discount.html
httemplate/search/elements/search-html.html
httemplate/search/elements/search.html
httemplate/search/report_cust_bill_pkg_discount.html
httemplate/search/report_svc_broadband.html
httemplate/search/svc_broadband-map.html
httemplate/search/svc_broadband.cgi

index c00a13f..66697ef 100644 (file)
@@ -3589,6 +3589,11 @@ sub list_tickets {
 
   # unavoidable false laziness w/ httemplate/view/cust_main/tickets.html
   if ( $FS::TicketSystem::system && FS::TicketSystem->selfservice_priority ) {
+
+    @tickets = grep { $_->{'_selfservice_priority'}
+                        !~ /^\s*(closed?|resolved?|done)\s*/i }
+                 @tickets;
+
     my $conf = new FS::Conf;
     my $dir = $conf->exists('ticket_system-priority_reverse') ? -1 : 1;
     +{ tickets => [ 
index f11beec..b24b3ab 100644 (file)
@@ -3010,6 +3010,7 @@ sub _parse_new_discounts {
         discountnum => $opt->{"${type}_discountnum"},
         amount      => $opt->{"${type}_discountnum_amount"},
         percent     => $opt->{"${type}_discountnum_percent"},
+        months      => $opt->{"${type}_discountnum_months"},
       };
     }
 
index 02b01f8..c8c6236 100644 (file)
@@ -80,6 +80,7 @@ for my $type (qw|setup_discountnum recur_discountnum|) {
     $change{$type} = $dnum;
     $change{"${type}_amount"}  = $cgi->param("${type}_amount");
     $change{"${type}_percent"} = $cgi->param("${type}_percent");
+    $change{"${type}_months"}  = $cgi->param("${type}_months");
   } elsif ($dnum eq '') {
     # Set discount as no discount
     $change{"${type}"} = 0;
index ce6249e..4d360b2 100644 (file)
@@ -1,3 +1,24 @@
+<%doc>
+
+Instead of:
+
+  my $link = $self_url. '?'. $cgi->query_string;
+
+which will fail when the query string exceeds ~2k (browser-dependent)
+
+
+Usage:
+
+  my $query = $m->scomp('/elements/create_uri_query');
+  my $link = $self_url. '?'. $query;
+
+You can also pass an optional 'secure'=>1 parameter to force handling as
+session data, even for short query strings.
+
+
+See also handle_uri_query which needs to be used by the target page.
+
+</%doc>
 <% $query %>\
 <%init>
 
@@ -14,7 +35,7 @@ if ( $opt{secure} ) {
 
 }
 
-my $query = $cgi->query_string;
+my $query = $opt{query} || $cgi->query_string;
 
 if ( length($query) > 1920 || $opt{secure} ) { #stupid IE 2083 URL limit
 
index 16935cf..012afff 100644 (file)
@@ -1,18 +1,19 @@
 % if ( $FS::CurrentUser::CurrentUser->access_right('Bulk send customer notices') ) {
-<A HREF="<%$p%>misc/email-customers.html?table=<%$table%>&agent_virt_agentnum=<%$agent_virt_agentnum%>&<%$query%>"><%$label%></A>
+<A HREF="<%$p%>misc/email-customers.html?<%$query%>"><%$label%></A>
 % }
 <%init>
 my %opt = @_;
-my $table = $opt{'table'};
-my $agent_virt_agentnum = $opt{'agent_virt_agentnum'};
 my $search_hash = $opt{'search_hash'};
-die "'table' required" if !$table;
+die "'table' required" if !$opt{'table'};
 die "'search_hash' required" if !$search_hash;
 
 my $uri = new URI;
 my @params = map { $_, $search_hash->{$_} } sort keys %$search_hash;
-$uri->query_form(@params);
-my $query = $uri->query;
+$uri->query_form( @params,
+                  table               => $opt{'table'},
+                  agent_virt_agentnum => $opt{'agent_virt_agentnum'}
+                );
+my $query = $m->scomp('/elements/create_uri_query', query=>$uri->query);
 my $label = ($opt{'label'} || 'Email a notice to these customers');
 </%init>
 
index 2dea96a..b86ef00 100644 (file)
@@ -1,9 +1,17 @@
+<%doc>
+
+Usage (before accessing any $cgi parameters):
+
+$m->comp('/elements/handle_uri_query');
+
+</%doc>
 <%init>
 
-my %opt = @_;
+#my %opt = @_;
 
 if ( $cgi->param('redirect') ) {
   my $session = $cgi->param('redirect');
+  my $maxrecords = $cgi->param('maxrecords');
 
   my $pref = $FS::CurrentUser::CurrentUser->option("redirect$session");
   die "unknown redirect session $session\n" unless length($pref);
@@ -16,5 +24,7 @@ if ( $cgi->param('redirect') ) {
     $cgi->param($param, $decrypted);
   }
 
+  $cgi->param('maxrecords', $maxrecords) if $maxrecords =~ /^(\d+)$/;
+
 }
 </%init>
index f52c6b3..3f8816c 100644 (file)
@@ -302,6 +302,8 @@ my $process_url = $opt{'process_url'} || 'process/email-customers.html';
 my $title = $opt{'title'} || 'Send customer notices';
 push( @no_search_fields, @{$opt{'no_search_fields'}} ) if $opt{'no_search_fields'};
 
+$m->comp('/elements/handle_uri_query');
+
 my $table = $cgi->param('table') or die "'table' required";
 my $agent_virt_agentnum = $cgi->param('agent_virt_agentnum') || '';
 
index c634828..f4fbd56 100644 (file)
+<%doc>
+
+Display the Discount Detail Report:
+
+Parameters:
+
+ - discount_classnum
+ - usernum
+ - agentnum
+ - beginning
+ - ending
+ - include_waived_setup
+
+</%doc>
 <& elements/search.html,
-                 'title'       => 'Discounts',
-                 'name'        => 'discounts',
-                 'query'       => $query,
-                 'count_query' => $count_query,
-                 'count_addl'  => [ $money_char. '%.2f total', ],
-                 'header'      => [
-                   #'#',
-                   'Discount',
-                   'Class',
-                   'Amount',
-                   'Months',
-                   'Package',
-                   'Invoice',
-                   'Date',
-                   FS::UI::Web::cust_header(),
-                 ],
-                 'fields'      => [
-                   #'billpkgdiscountnum',
-                   sub { $_[0]->cust_pkg_discount->discount->description },
-                   sub { $_[0]->cust_pkg_discount->discount->classname },
-                   sub { sprintf($money_char.'%.2f', shift->amount ) },
-                   $months_sub,
-                   'pkg',#sub { $_[0]->cust_bill_pkg->cust_pkg->part_pkg->pkg },
-                   'invnum',
-                   sub { time2str('%b %d %Y', shift->_date ) },
-                   \&FS::UI::Web::cust_fields,
-                 ],
-                 'sort_fields' => [
-                   '',
-                   '',
-                   'amount',
-                   'months',
-                   'pkg',
-                   'invnum',
-                   '_date',
-                 ],
-                 'links'       => [
-                   #'',
-                   '', #link to customer discount???
-                   '',
-                   '',
-                   '',
-                   '',
-                   $ilink,
-                   $ilink,
-                   ( map { $_ ne 'Cust. Status' ? $clink : '' }
-                         FS::UI::Web::cust_header()
-                   ),
-                 ],
-                 #'align' => 'rlrrrc'.FS::UI::Web::cust_aligns(),
-                 'align' => 'lcrrlrr'.FS::UI::Web::cust_aligns(),
-                 'color' => [ 
-                              #'',
-                              '',
-                              '',
-                              '',
-                              '',
-                              '',
-                              '',
-                              '',
-                              FS::UI::Web::cust_colors(),
-                            ],
-                 'style' => [ 
-                              #'',
-                              '',
-                              '',
-                              '',
-                              '',
-                              '',
-                              '',
-                              '',
-                              FS::UI::Web::cust_styles(),
-                            ],
+  title       => 'Discounts',
+  name        => 'discounts',
+  query       => $query,
+  count_query => $count_query,
+  count_addl  => [ $money_char . '%.2f total' ],
+
+  header => [
+    qw(
+      Discount
+      Class
+      Amount
+      Months
+      Package
+      Invoice
+      Date
+    ),
+    FS::UI::Web::cust_header(),
+  ],
+
+  fields => [
+    # Discount
+    sub {
+        if ( $_[0]->pkgdiscountnum ) {
+            # Standard discount, not a waived setup fee
+            my $discount = qsearchs('discount',{
+                pkgdiscountnum => $_[0]->pkgdiscountnum
+            });
+            return $discount->description;
+        } else {
+            return 'Waive setup fee';
+        }
+    },
+
+    # Class
+    sub {
+        if ( $_[0]->discountnum ) {
+            # Standard discount, not a waived setup fee
+            my $discount = qsearchs('discount',{
+                discountnum => $_[0]->discountnum
+            });
+            return $discount->classname;
+        } else {
+            return 'n/a';
+        }
+    },
+
+    # Amount
+    sub {
+      sprintf(
+        $money_char.'%.2f',
+        $_[0]->amount ? $_[0]->amount : $_[0]->setup_fee
+      )
+    },
+
+    # Months
+    sub {
+      my $row = shift;
+      if ($row->pkgdiscountnum) {
+        $row->setuprecur eq 'setup'
+          ? 'Setup'
+          : sprintf( '%.2f', $row->months ),
+      } else {
+        return 'Setup';
+      }
+    },
+
+    # Package
+    'pkg',
+
+    # Invoice
+    'invnum',
+
+    # Date
+    sub { time2str('%b %d %Y', $_[0]->_date) },
+
+    # Customer
+    \&FS::UI::Web::cust_fields,
+  ],
+
+  sort_fields => [
+    '',       # Discount
+    '',       # Class
+    'amount', # Amount
+    'months', # Months
+    'pkg',    # Package
+    'invnum', # Invoice
+    '_date',  # Date
+  ],
+
+  links => [
+    '', # Discount
+    '', # Class
+    '', # Amount
+    '', # Months
+    '', # Package
+    [ "${p}view/cust_bill.cgi?", 'invnum' ], # Invoice
+    [ "${p}view/cust_bill.cgi?", 'invnum' ], # Date
+    (   # Customer
+      map {
+        $_ ne 'Cust. Status'
+          ? [ "${p}view/cust_main.cgi?", 'custnum' ]
+          : ''
+      } FS::UI::Web::cust_header()
+    ),
+  ],
+
+  align => 'lcrrlrr'.FS::UI::Web::cust_aligns(),
+  color => [ '','','','','','','',FS::UI::Web::cust_colors() ],
+  style => [ '','','','','','','',FS::UI::Web::cust_styles() ],
            
 &>
 <%init>
 
-#a little false laziness below w/cust_bill_pkg.cgi
-
 die "access denied"
   unless $FS::CurrentUser::CurrentUser->access_right('Financial reports');
 
 my $conf = new FS::Conf;
 
-#here is the agent virtualization
-my $agentnums_sql =
-  $FS::CurrentUser::CurrentUser->agentnums_sql( 'table' => 'cust_main' );
+# Query building blocks
+my @select = (qw(
+  cust_bill_pkg_discount.billpkgdiscountnum
+  cust_bill_pkg_discount.pkgdiscountnum
+  cust_bill_pkg_discount.amount
+  cust_bill_pkg_discount.months
+
+  cust_bill.invnum
+  cust_bill._date
+
+  part_pkg.pkg
+
+  cust_main.custnum
+
+  cust_pkg_discount.setuprecur
+  cust_pkg_discount.discountnum
+  cust_pkg.waive_setup),
+
+  "
+  (  SELECT optionvalue
+     FROM part_pkg_option
+     WHERE
+        part_pkg_option.pkgpart = cust_pkg.pkgpart
+        AND optionname = 'setup_fee'
+  ) as setup_fee  ",
+
+  "
+  COALESCE(
+      CAST(cust_bill_pkg_discount.amount AS TEXT),
+      (  SELECT optionvalue
+         FROM part_pkg_option
+         WHERE
+            part_pkg_option.pkgpart = cust_pkg.pkgpart
+            AND optionname = 'setup_fee'
+      )
+  ) as discountorwaive
+  ",
+
+  FS::UI::Web::cust_sql_fields(),
+);
+
+my $join = "
+LEFT JOIN cust_bill_pkg_discount
+  USING (billpkgnum)
 
-my @where = ( $agentnums_sql );
+LEFT JOIN cust_pkg_discount
+  ON cust_bill_pkg_discount.pkgdiscountnum = cust_pkg_discount.pkgdiscountnum
 
+LEFT JOIN cust_pkg
+  ON cust_bill_pkg.pkgnum = cust_pkg.pkgnum
+
+LEFT JOIN part_pkg
+  USING (pkgpart)
+
+LEFT JOIN cust_bill USING (invnum)
+
+LEFT JOIN cust_main
+  ON cust_bill.custnum = cust_main.custnum
+
+";
+
+# Each entry in @where will be joined with AND
+my @where = (
+
+  # Agent Virtualization
+  $FS::CurrentUser::CurrentUser->agentnums_sql(table => 'cust_main'),
+
+  # Select only rows where there is a discount or waived setup fee
+  "(
+    cust_bill_pkg_discount.billpkgdiscountnum IS NOT NULL
+    OR (
+      cust_pkg.setup = cust_bill_pkg.sdate
+      AND cust_pkg.waive_setup = 'Y'
+    )
+  )",
+
+);
+
+
+# Filter: Date Range
 my($beginning, $ending) = FS::UI::Web::parse_beginning_ending($cgi);
-push @where, "_date >= $beginning",
-             "_date <= $ending";
+push @where, "_date >= $beginning", "_date <= $ending";
+
 
+# Filter: Agent
 if ( $cgi->param('agentnum') =~ /^(\d+)$/ ) {
   push @where, "cust_main.agentnum = $1";
 }
 
-#usernum
+
+# Filter: User
 if ( $cgi->param('usernum') =~ /^(\d+)$/ ) {
-  push @where, "cust_pkg_discount.usernum = $1";
+  push @where,
+    "( cust_pkg_discount.usernum = $1 OR cust_pkg_discount.usernum IS NULL )";
 }
 
-# (discount) classnum
-my $join_discount = '';
-#false laziness w/cust_pkg_discount.html and cust_pkg.pm::search
+# Filter: Include waived setup fees
+if ( !$cgi->param('include_waived_setup') ) {
+  push @where, "cust_bill_pkg_discount.pkgdiscountnum IS NOT NULL";
+}
+
+# Filter: Discount Class
 if ( grep { $_ eq 'discount_classnum' } $cgi->param ) {
 
 #  my @classnum = ();
@@ -128,7 +256,7 @@ if ( grep { $_ eq 'discount_classnum' } $cgi->param ) {
    if ( $cgi->param('discount_classnum') =~ /^(\d*)$/ && $1 ne '0' ) {
     my @classnum = ( $1 );
 
-    $join_discount = 'LEFT JOIN discount USING (discountnum)';
+    $join .= ' LEFT JOIN discount USING (discountnum) ';
 
     my @c_where = ();
     my @nums = grep $_, @classnum;
@@ -169,40 +297,32 @@ if ( grep { $_ eq 'discount_classnum' } $cgi->param ) {
 #   }
 # }
 
-my $count_query = "SELECT COUNT(*), SUM(cust_bill_pkg_discount.amount)";
-
-my $join_cust_pkg_discount =
-  'LEFT JOIN cust_pkg_discount USING (pkgdiscountnum)';
-
-my $join_cust =
-  '         JOIN cust_bill USING ( invnum ) '.
-  FS::UI::Web::join_cust_main('cust_bill', 'cust_pkg');
-
-my $join_pkg =
-  '    JOIN cust_bill_pkg USING ( billpkgnum )
-  LEFT JOIN cust_pkg ON ( cust_bill_pkg.pkgnum = cust_pkg.pkgnum )
-  LEFT JOIN part_pkg USING ( pkgpart ) ';
-  #LEFT JOIN part_pkg AS override
-  #  ON pkgpart_override = override.pkgpart ';
-
-my $join = "$join_cust_pkg_discount $join_discount $join_pkg $join_cust";
+my $count_query;
+if ( $cgi->param('include_waived_setup') ) {
+  $count_query = "
+    SELECT
+      COUNT(*),
+      SUM(
+        COALESCE(
+          cust_bill_pkg_discount.amount,
+          CAST((  SELECT optionvalue
+             FROM part_pkg_option
+             WHERE
+                part_pkg_option.pkgpart = cust_pkg.pkgpart
+                AND optionname = 'setup_fee'
+          ) AS NUMERIC )
+        )
+      ) ";
+} else {
+  $count_query = "SELECT COUNT(*), SUM(cust_bill_pkg_discount.amount)";
+}
 
 my $where = ' WHERE '. join(' AND ', @where);
 
-$count_query .= " FROM cust_bill_pkg_discount $join $where";
-
-my @select = (
-               'cust_bill_pkg_discount.*',
-               #'cust_bill_pkg.*',
-               'cust_bill.invnum',
-               'cust_bill._date',
-             );
-push @select, 'part_pkg.pkg';
-push @select, 'cust_main.custnum',
-              FS::UI::Web::cust_sql_fields();
+$count_query .= " FROM cust_bill_pkg $join $where";
 
 my $query = {
-  'table'     => 'cust_bill_pkg_discount',
+  'table'     => 'cust_bill_pkg',
   'addl_from' => $join,
   'hashref'   => {},
   'select'    => join(', ', @select ),
@@ -210,17 +330,6 @@ my $query = {
   'order_by'  => 'ORDER BY _date, billpkgdiscountnum',
 };
 
-my $ilink = [ "${p}view/cust_bill.cgi?", 'invnum' ];
-my $clink = [ "${p}view/cust_main.cgi?", 'custnum' ];
-
-my $conf = new FS::Conf;
 my $money_char = $conf->config('money_char') || '$';
 
-my $months_sub = sub {
-  my $cust_bill_pkg_discount = shift;
-  return 'Setup'
-    if $cust_bill_pkg_discount->cust_pkg_discount->setuprecur eq 'setup';
-  sprintf('%.2f', $cust_bill_pkg_discount->months);
-};
-
 </%init>
index 147a2d9..29e0999 100644 (file)
@@ -95,8 +95,9 @@
 %               {
 %                 $cgi->delete('maxrecords');
 %                 $cgi->param('_dummy', 1);
+%                 my $query = $m->scomp('/elements/create_uri_query');
 
-                  ( show <SELECT NAME="maxrecords" onChange="window.location = '<% "$self_url?". $cgi->query_string %>;maxrecords=' + this.options[this.selectedIndex].value;">
+                  ( show <SELECT NAME="maxrecords" onChange="window.location = '<% "$self_url?$query" %>;maxrecords=' + this.options[this.selectedIndex].value;">
 
 %                   foreach my $max ( map { $_ * $confmax } qw( 1 5 10 25 ) ) {
                   <OPTION VALUE="<% $max %>" <% ( $maxrecords == $max ) ? 'SELECTED' : '' %>><% $max %></OPTION>
                 <% $opt{'download_label'} || 'Download results:' %>
 
 %               $cgi->param('_type', "$xlsname.xls" ); 
-                <A HREF="<% "$self_url?". $cgi->query_string %>">Spreadsheet</A>&nbsp;|&nbsp;
+%               my $query = $m->scomp('/elements/create_uri_query');
+                <A HREF="<% "$self_url?$query" %>">Spreadsheet</A>&nbsp;|&nbsp;
 
 %               $cgi->param('_type', 'csv'); 
-                <A HREF="<% "$self_url?". $cgi->query_string %>">CSV</A>&nbsp;|&nbsp;
+%               my $query = $m->scomp('/elements/create_uri_query');
+                <A HREF="<% "$self_url?$query" %>">CSV</A>&nbsp;|&nbsp;
 
 %             if ( defined($opt{xml_elements}) ) {
 %               $cgi->param('_type', 'xml'); 
-                <A HREF="<% "$self_url?". $cgi->query_string %>">XML</A>&nbsp;|&nbsp;
+%               my $query = $m->scomp('/elements/create_uri_query');
+                <A HREF="<% "$self_url?$query" %>">XML</A>&nbsp;|&nbsp;
 %             }
 
 %               $cgi->param('_type', 'html-print'); 
-                <A HREF="<% "$self_url?". $cgi->query_string %>">webpage</A>
+%               my $query = $m->scomp('/elements/create_uri_query');
+                <A HREF="<% "$self_url?$query" %>">webpage</A>
 
 %# "save search" -- for now, obey disable_download and the 'Download
 %# report data' ACL, because saving a search allows the user to receive
@@ -307,8 +312,8 @@ my $self_url = $cgi->url('-path_info' => 1, '-full' =>1);
 %     } else {
 %       $cgi->param('order_by', $field);
 %     }
-%     $label = qq(<A HREF="$self_url?). $cgi->query_string.
-%              qq(">$label</A>);
+%     my $query = $m->scomp('/elements/create_uri_query');
+%     $label = qq(<A HREF="$self_url?$query">$label</A>);
 %   }
 %
 %   $colspan = ref($header) ? $header->{colspan} : 0;
index 18b4c0e..0e8c69a 100644 (file)
@@ -222,6 +222,8 @@ my(%opt) = @_;
 
 my $curuser = $FS::CurrentUser::CurrentUser;
 
+$m->comp('/elements/handle_uri_query');
+
 my $type = $cgi->param('_type') =~ /^(csv|\w*\.xls|xml|select|html(-print)?)$/
            ? $1 : 'html' ;
 
index 10ccba9..6412379 100644 (file)
 
   <& /elements/tr-input-beginning_ending.html &>
 
+  <& /elements/tr-checkbox.html,
+        label => 'Include waived setup fees:',
+        field => 'include_waived_setup',
+        value => 'Y',
+  &>
+
 <!-- doesn't actually work yet, needs support in cust_bill_pkg_discount.html
   <& /elements/tr-input-lessthan_greaterthan.html,
        'label' => 'Amount',
index 210112b..45246c7 100755 (executable)
@@ -1,6 +1,6 @@
 <% include('/elements/header.html', $title ) %>
 
-<FORM ACTION="svc_broadband.cgi" METHOD="GET">
+<FORM ACTION="svc_broadband.cgi" METHOD="POST">
 <INPUT TYPE="hidden" NAME="magic" VALUE="advanced">
 <INPUT TYPE="hidden" NAME="custnum" VALUE="<% $custnum %>">
 %# extensive false laziness with svc_acct
index 41f4b8d..65830b5 100755 (executable)
@@ -10,6 +10,8 @@ die "access denied" unless
 
 my $conf = new FS::Conf;
 
+$m->comp('/elements/handle_uri_query');
+
 my @features; # geoJSON structure
 
 # accept all the search logic from svc_broadband.cgi...
index 80345dc..53a0aa0 100755 (executable)
@@ -82,6 +82,8 @@ my %cust_pkg_cache;
 
 my $conf = new FS::Conf;
 
+$m->comp('/elements/handle_uri_query');
+
 my %search_hash;
 if ( $cgi->param('magic') eq 'unlinked' ) {
   %search_hash = ( 'unlinked' => 1 );
@@ -132,9 +134,12 @@ my $html_init = include('/elements/email-link.html',
                   'search_hash' => \%search_hash,
                   'table' => 'svc_broadband' 
                 );
+
+my $query = $m->scomp('/elements/create_uri_query');
+
 $html_init .= ' | ' .
   '<a href="' .
-  $fsurl . 'search/svc_broadband-map.html?' . $cgi->query_string .
+  $fsurl . 'search/svc_broadband-map.html?' . $query .
   '">' . emt('View a map of these services') . '</a>';
 
 my (@header_pkg,@fields_pkg,@blank_pkg);