diff options
-rw-r--r-- | FS/FS/ClientAPI/MyAccount.pm | 5 | ||||
-rw-r--r-- | FS/FS/cust_pkg.pm | 1 | ||||
-rw-r--r-- | httemplate/edit/process/change-cust_pkg.html | 1 | ||||
-rw-r--r-- | httemplate/elements/create_uri_query | 23 | ||||
-rw-r--r-- | httemplate/elements/email-link.html | 13 | ||||
-rw-r--r-- | httemplate/elements/handle_uri_query | 12 | ||||
-rw-r--r-- | httemplate/misc/email-customers.html | 2 | ||||
-rw-r--r-- | httemplate/search/cust_bill_pkg_discount.html | 363 | ||||
-rw-r--r-- | httemplate/search/elements/search-html.html | 19 | ||||
-rw-r--r-- | httemplate/search/elements/search.html | 2 | ||||
-rw-r--r-- | httemplate/search/report_cust_bill_pkg_discount.html | 6 | ||||
-rwxr-xr-x | httemplate/search/report_svc_broadband.html | 2 | ||||
-rwxr-xr-x | httemplate/search/svc_broadband-map.html | 2 | ||||
-rwxr-xr-x | httemplate/search/svc_broadband.cgi | 7 |
14 files changed, 314 insertions, 144 deletions
diff --git a/FS/FS/ClientAPI/MyAccount.pm b/FS/FS/ClientAPI/MyAccount.pm index c00a13f2b..66697efb5 100644 --- a/FS/FS/ClientAPI/MyAccount.pm +++ b/FS/FS/ClientAPI/MyAccount.pm @@ -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 => [ diff --git a/FS/FS/cust_pkg.pm b/FS/FS/cust_pkg.pm index f11beec7d..b24b3abe3 100644 --- a/FS/FS/cust_pkg.pm +++ b/FS/FS/cust_pkg.pm @@ -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"}, }; } diff --git a/httemplate/edit/process/change-cust_pkg.html b/httemplate/edit/process/change-cust_pkg.html index 02b01f8de..c8c623641 100644 --- a/httemplate/edit/process/change-cust_pkg.html +++ b/httemplate/edit/process/change-cust_pkg.html @@ -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; diff --git a/httemplate/elements/create_uri_query b/httemplate/elements/create_uri_query index ce6249e0e..4d360b255 100644 --- a/httemplate/elements/create_uri_query +++ b/httemplate/elements/create_uri_query @@ -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 diff --git a/httemplate/elements/email-link.html b/httemplate/elements/email-link.html index 16935cf98..012afff1a 100644 --- a/httemplate/elements/email-link.html +++ b/httemplate/elements/email-link.html @@ -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> diff --git a/httemplate/elements/handle_uri_query b/httemplate/elements/handle_uri_query index 2dea96a6d..b86ef0092 100644 --- a/httemplate/elements/handle_uri_query +++ b/httemplate/elements/handle_uri_query @@ -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> diff --git a/httemplate/misc/email-customers.html b/httemplate/misc/email-customers.html index f52c6b36a..3f8816caa 100644 --- a/httemplate/misc/email-customers.html +++ b/httemplate/misc/email-customers.html @@ -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') || ''; diff --git a/httemplate/search/cust_bill_pkg_discount.html b/httemplate/search/cust_bill_pkg_discount.html index c63482827..f4fbd561b 100644 --- a/httemplate/search/cust_bill_pkg_discount.html +++ b/httemplate/search/cust_bill_pkg_discount.html @@ -1,110 +1,238 @@ +<%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> diff --git a/httemplate/search/elements/search-html.html b/httemplate/search/elements/search-html.html index 147a2d984..29e0999c9 100644 --- a/httemplate/search/elements/search-html.html +++ b/httemplate/search/elements/search-html.html @@ -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> @@ -139,18 +140,22 @@ <% $opt{'download_label'} || 'Download results:' %> % $cgi->param('_type', "$xlsname.xls" ); - <A HREF="<% "$self_url?". $cgi->query_string %>">Spreadsheet</A> | +% my $query = $m->scomp('/elements/create_uri_query'); + <A HREF="<% "$self_url?$query" %>">Spreadsheet</A> | % $cgi->param('_type', 'csv'); - <A HREF="<% "$self_url?". $cgi->query_string %>">CSV</A> | +% my $query = $m->scomp('/elements/create_uri_query'); + <A HREF="<% "$self_url?$query" %>">CSV</A> | % if ( defined($opt{xml_elements}) ) { % $cgi->param('_type', 'xml'); - <A HREF="<% "$self_url?". $cgi->query_string %>">XML</A> | +% my $query = $m->scomp('/elements/create_uri_query'); + <A HREF="<% "$self_url?$query" %>">XML</A> | % } % $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; diff --git a/httemplate/search/elements/search.html b/httemplate/search/elements/search.html index 18b4c0ec5..0e8c69a51 100644 --- a/httemplate/search/elements/search.html +++ b/httemplate/search/elements/search.html @@ -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' ; diff --git a/httemplate/search/report_cust_bill_pkg_discount.html b/httemplate/search/report_cust_bill_pkg_discount.html index 10ccba912..6412379f2 100644 --- a/httemplate/search/report_cust_bill_pkg_discount.html +++ b/httemplate/search/report_cust_bill_pkg_discount.html @@ -24,6 +24,12 @@ <& /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', diff --git a/httemplate/search/report_svc_broadband.html b/httemplate/search/report_svc_broadband.html index 210112bc4..45246c74a 100755 --- a/httemplate/search/report_svc_broadband.html +++ b/httemplate/search/report_svc_broadband.html @@ -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 diff --git a/httemplate/search/svc_broadband-map.html b/httemplate/search/svc_broadband-map.html index 41f4b8dfd..65830b5d2 100755 --- a/httemplate/search/svc_broadband-map.html +++ b/httemplate/search/svc_broadband-map.html @@ -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... diff --git a/httemplate/search/svc_broadband.cgi b/httemplate/search/svc_broadband.cgi index 80345dc91..53a0aa097 100755 --- a/httemplate/search/svc_broadband.cgi +++ b/httemplate/search/svc_broadband.cgi @@ -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); |