From ce9a9630a2232dafc952bdaadb627fcc3a5558f9 Mon Sep 17 00:00:00 2001 From: Jonathan Prykop Date: Mon, 16 Feb 2015 20:02:30 -0600 Subject: RT#23598: Feature Request - Email notice to A/R Report Results --- .../search/elements/cust_main_dayranges.html | 28 ++++++++++++++++++++++ httemplate/search/report_receivables.cgi | 1 + 2 files changed, 29 insertions(+) diff --git a/httemplate/search/elements/cust_main_dayranges.html b/httemplate/search/elements/cust_main_dayranges.html index 5dbece861..73a429f8a 100644 --- a/httemplate/search/elements/cust_main_dayranges.html +++ b/httemplate/search/elements/cust_main_dayranges.html @@ -5,6 +5,7 @@ Example: <& elements/cust_main_dayranges.html, 'title' => 'Accounts Receivable Aging Summary', 'range_sub' => $mysub, + 'email_link' => 1, #adds an action column with an email link if true &> my $mysub = sub { @@ -27,6 +28,7 @@ Example: '90+', emt('Total'), @pay_head, + @act_header, ], 'footer' => [ 'Total', @@ -42,6 +44,7 @@ Example: sprintf( ''.$money_char.'%.2f', $row->{'rangecol_0_0'} ), ('') x @pay_labels, + @act_blank, ], 'fields' => [ FS::UI::Web::cust_fields_subs(), @@ -51,6 +54,7 @@ Example: format_rangecol('90_0'), format_rangecol('0_0'), @pay_labels, + @act_fields, ], 'links' => [ ( map { $_ ne 'Cust. Status' ? $clink : '' } @@ -62,22 +66,32 @@ Example: '', '', @pay_links, + @act_blank, ], + 'link_onclicks' => [ ( map '', @cust_header ), + '', '', '', '', '', + ( map '', @pay_labels ), + @act_link_onclicks, + ], 'align' => FS::UI::Web::cust_aligns(). 'rrrrr'. ('c' x @pay_labels), + @act_align, 'size' => [ ( map '', @cust_header ), #'-1', '', '', '', '', '', ], '', '', '', '', '', '', ( map '', @pay_labels ), + @act_blank, ], 'style' => [ FS::UI::Web::cust_styles(), #'b', '', '', '', '', 'b', ], '', '', '', '', 'b', ( map '', @pay_labels ), + @act_blank, ], 'xls_format' => [ (map '', FS::UI::Web::cust_styles), '', '', '', '', { bold => 1 }, + @act_blank, ], 'color' => [ FS::UI::Web::cust_colors(), @@ -88,6 +102,7 @@ Example: '', '', ( map '', @pay_labels ), + @act_blank, ], %opt, &> @@ -235,6 +250,19 @@ if($opt{'payment_links'} && $curuser->access_right('Process payment') && @payby) @payby ); } +my (@act_header, @act_fields, @act_link_onclicks, @act_align, @act_blank); +if (delete($opt{'email_links'})) { + push @act_header, 'Actions'; + push @act_fields, sub { 'send email' }; + push @act_link_onclicks, sub { + my $row = shift; + my $custnum = $row->custnum; + return qq!window.open('${p}misc/email-customers.html?table=cust_main&custnum=$custnum','_blank')!; + }; + push @act_align, 'l'; + push @act_blank, ''; +} + <%once> diff --git a/httemplate/search/report_receivables.cgi b/httemplate/search/report_receivables.cgi index 9c5c0e2d9..bca2a057a 100755 --- a/httemplate/search/report_receivables.cgi +++ b/httemplate/search/report_receivables.cgi @@ -2,6 +2,7 @@ 'title' => emt('Accounts Receivable Aging Summary'), 'range_sub' => \&balance, 'payment_links' => 1, + 'email_links' => 1, &> <%init> -- cgit v1.2.1 From 7a8ff6a0a75e0a50b6fde0bff3d49e8372853e94 Mon Sep 17 00:00:00 2001 From: Jonathan Prykop Date: Tue, 17 Feb 2015 13:47:18 -0600 Subject: RT#32089: Ignore services when using packages based on active services --- FS/FS/part_pkg/bulk.pm | 2 +- FS/FS/part_pkg/bulk_Common.pm | 24 +++++++++++++++++++++++- FS/FS/part_pkg/bulk_simple.pm | 2 +- 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/FS/FS/part_pkg/bulk.pm b/FS/FS/part_pkg/bulk.pm index 4a55858de..bc42e20d2 100644 --- a/FS/FS/part_pkg/bulk.pm +++ b/FS/FS/part_pkg/bulk.pm @@ -27,7 +27,7 @@ $me = '[FS::part_pkg::bulk]'; sub _bulk_cust_svc { my( $self, $cust_pkg, $sdate ) = @_; # END START - $cust_pkg->h_cust_svc( $$sdate, $cust_pkg->last_bill ); + return $self->_only_svcs_filter($cust_pkg->h_cust_svc( $$sdate, $cust_pkg->last_bill )); } sub _bulk_setup { diff --git a/FS/FS/part_pkg/bulk_Common.pm b/FS/FS/part_pkg/bulk_Common.pm index 67f2caf44..a9231bc5c 100644 --- a/FS/FS/part_pkg/bulk_Common.pm +++ b/FS/FS/part_pkg/bulk_Common.pm @@ -5,6 +5,7 @@ use strict; use vars qw($DEBUG $me %info); use Date::Format; use FS::Conf; +use FS::Record qw(qsearchs); $DEBUG = 0; $me = '[FS::part_pkg::bulk_Common]'; @@ -23,8 +24,17 @@ $me = '[FS::part_pkg::bulk_Common]'; 'instead of a detailed list', 'type' => 'checkbox', }, + 'only_svcs' => { + 'name' => 'Only charge fees for these services', + 'type' => 'select_multiple', + 'select_table' => 'part_svc', + 'select_key' => 'svcpart', + 'select_label' => 'svc', + 'disable_empty' => 1, + 'parse' => sub { @_ }, #should this be the default in /edit/process/part_pkg.cgi? + }, }, - 'fieldorder' => [ 'svc_setup_fee', 'svc_recur_fee', + 'fieldorder' => [ 'svc_setup_fee', 'svc_recur_fee', 'only_svcs', 'summarize_svcs', 'no_prorate' ], 'weight' => 51, ); @@ -123,5 +133,17 @@ sub is_free_options { sub can_usageprice { 0; } +sub _only_svcs_filter { + my ($self, @cust_svc) = @_; + my @only_svcs = split(', ',$self->option('only_svcs',1)); + if (@only_svcs) { + @cust_svc = grep { + my $svcpart = $_->svcpart; + grep(/^$svcpart$/,@only_svcs); + } @cust_svc; + } + return @cust_svc; +} + 1; diff --git a/FS/FS/part_pkg/bulk_simple.pm b/FS/FS/part_pkg/bulk_simple.pm index 93944cc0a..6ed125022 100644 --- a/FS/FS/part_pkg/bulk_simple.pm +++ b/FS/FS/part_pkg/bulk_simple.pm @@ -18,7 +18,7 @@ $me = '[FS::part_pkg::bulk]'; sub _bulk_cust_svc { my( $self, $cust_pkg, $sdate ) = @_; - $cust_pkg->cust_svc; + return $self->_only_svcs_filter($cust_pkg->cust_svc); } sub _bulk_setup { -- cgit v1.2.1 From 0c2cb2d865f84d21032ebc9780118d44df4ddf26 Mon Sep 17 00:00:00 2001 From: Jonathan Prykop Date: Tue, 17 Feb 2015 18:11:21 -0600 Subject: #14671: Usage for current day when billing outstanding usage (for cancelling customers) [various fixes to previous] --- FS/FS/cust_pkg.pm | 50 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 20 deletions(-) diff --git a/FS/FS/cust_pkg.pm b/FS/FS/cust_pkg.pm index 7678a0295..fb3b0ff80 100644 --- a/FS/FS/cust_pkg.pm +++ b/FS/FS/cust_pkg.pm @@ -901,7 +901,6 @@ sub cancel { return $error; } } - } #unless $date my %hash = $self->hash; @@ -936,9 +935,13 @@ sub cancel { foreach my $supp_pkg ( $self->supplemental_pkgs ) { if ($delay_cancel) { - $error = $supp_pkg->suspend(%options, 'from_main' => 1, 'reason' => undef); + $error = $supp_pkg->suspend( + 'from_main' => 1, + 'from_cancel' => 1, + 'time' => $cancel_time + ); } else { - $error = $supp_pkg->cancel(%options, 'from_main' => 1); + $error = $supp_pkg->cancel(%options, 'from_main' => 1); } if ( $error ) { $dbh->rollback if $oldAutoCommit; @@ -946,11 +949,13 @@ sub cancel { } } - foreach my $usage ( $self->cust_pkg_usage ) { - $error = $usage->delete; - if ( $error ) { - $dbh->rollback if $oldAutoCommit; - return "deleting usage pools: $error"; + unless ($date) { + foreach my $usage ( $self->cust_pkg_usage ) { + $error = $usage->delete; + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return "deleting usage pools: $error"; + } } } @@ -1249,6 +1254,9 @@ separately. =item from_main - allows a supplemental package to be suspended, rather than redirecting the method call to its main package. For internal use. +=item from_cancel - used when suspending from the cancel method, forces +this to skip everything besides basic suspension. For internal use. + =back If there is an error, returns the error, otherwise returns false. @@ -1291,7 +1299,7 @@ sub suspend { } # some false laziness with sub cancel - if ( !$options{nobill} && !$date && + if ( !$options{nobill} && !$date && !$options{'from_cancel'} && $self->part_pkg->option('bill_suspend_as_cancel',1) ) { # kind of a kludge--'bill_suspend_as_cancel' to avoid having to # make the entire cust_main->bill path recognize 'suspend' and @@ -1356,17 +1364,19 @@ sub suspend { unless ( $date ) { # then we are suspending now - # credit remaining time if appropriate - # (if required by the package def, or the suspend reason) - my $unused_credit = $self->part_pkg->option('unused_credit_suspend',1) - || ( defined($reason) && $reason->unused_credit ); + unless ($options{'from_cancel'}) { + # credit remaining time if appropriate + # (if required by the package def, or the suspend reason) + my $unused_credit = $self->part_pkg->option('unused_credit_suspend',1) + || ( defined($reason) && $reason->unused_credit ); - if ( $unused_credit ) { - warn "crediting unused time on pkg#".$self->pkgnum."\n" if $DEBUG; - my $error = $self->credit_remaining('suspend', $suspend_time); - if ($error) { - $dbh->rollback if $oldAutoCommit; - return $error; + if ( $unused_credit ) { + warn "crediting unused time on pkg#".$self->pkgnum."\n" if $DEBUG; + my $error = $self->credit_remaining('suspend', $suspend_time); + if ($error) { + $dbh->rollback if $oldAutoCommit; + return $error; + } } } @@ -1397,7 +1407,7 @@ sub suspend { } my $conf = new FS::Conf; - if ( $conf->config('suspend_email_admin') ) { + if ( $conf->config('suspend_email_admin') && !$options{'from_cancel'} ) { my $error = send_email( 'from' => $conf->config('invoice_from', $self->cust_main->agentnum), -- cgit v1.2.1 From dba9a62fa32e07d4461e9c081201f69c0cda7015 Mon Sep 17 00:00:00 2001 From: Jonathan Prykop Date: Tue, 17 Feb 2015 18:13:04 -0600 Subject: fixed hanging bracket in Conf --- FS/FS/Conf.pm | 2 -- 1 file changed, 2 deletions(-) diff --git a/FS/FS/Conf.pm b/FS/FS/Conf.pm index bb04d9427..169f9fe16 100644 --- a/FS/FS/Conf.pm +++ b/FS/FS/Conf.pm @@ -2146,8 +2146,6 @@ and customer address. Include units.', 'type' => 'checkbox', }, - { - { 'key' => 'show_ship_company', 'section' => 'UI', -- cgit v1.2.1 From e11f3188435b30c193fd1443913ed77953e14dea Mon Sep 17 00:00:00 2001 From: Mark Wells Date: Wed, 18 Feb 2015 15:50:45 -0800 Subject: use media type codes in broadband subscription report, #28020 --- FS/FS/Report/FCC_477.pm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/FS/FS/Report/FCC_477.pm b/FS/FS/Report/FCC_477.pm index c93c919ea..75ddee0d7 100644 --- a/FS/FS/Report/FCC_477.pm +++ b/FS/FS/Report/FCC_477.pm @@ -400,7 +400,8 @@ sub fbs_sql { my @select = ( "$censustract AS censustract", - 'technology', + '(technology - technology % 10) AS media_type', + # media types are multiples of 10 'broadband_downstream', 'broadband_upstream', "SUM($q)", -- cgit v1.2.1 From 53a39f74f4735253591e6df083522b3a3bbacd6d Mon Sep 17 00:00:00 2001 From: Mark Wells Date: Wed, 18 Feb 2015 15:50:51 -0800 Subject: in FCC options editor, jump back to correct page after submitting, #32638 --- httemplate/browse/part_pkg-fcc.html | 9 ++++++++- httemplate/edit/process/bulk-part_pkg-fcc.html | 12 ++++++++---- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/httemplate/browse/part_pkg-fcc.html b/httemplate/browse/part_pkg-fcc.html index bdfb99a59..69e7d8f31 100755 --- a/httemplate/browse/part_pkg-fcc.html +++ b/httemplate/browse/part_pkg-fcc.html @@ -197,6 +197,13 @@ my $html_form = qq!

'; +# pass the page selection through so we can jump back to the current spot +if ( $cgi->param('maxrecords') =~ /^(\d+)$/ ) { + $html_form .= qq!!; +} +if ( $cgi->param('offset') =~ /^(\d+)$/ ) { + $html_form .= qq!!; +} # restore this only after creating $html_form $cgi->param('classnum', $classnum) if length($classnum); @@ -228,7 +235,7 @@ my @menubar = } function filter_change() { - window.location = '! . $cgi->self_url . qq!?classnum=' + window.location = '<% $cgi->self_url %>?classnum=' + document.getElementById('classnum').value; } diff --git a/httemplate/edit/process/bulk-part_pkg-fcc.html b/httemplate/edit/process/bulk-part_pkg-fcc.html index 8ef330829..d060a242e 100644 --- a/httemplate/edit/process/bulk-part_pkg-fcc.html +++ b/httemplate/edit/process/bulk-part_pkg-fcc.html @@ -17,7 +17,7 @@ % } <% $cgi->redirect($fsurl.'browse/part_pkg-fcc.html?redirect='.$session) %> % } else { -<% $cgi->redirect($fsurl.'browse/part_pkg-fcc.html?classnum='.$classnum.$jump) %> +<% $cgi->redirect($dest) %> % } <%init> my $curuser = $FS::CurrentUser::CurrentUser; @@ -38,10 +38,14 @@ foreach my $param ($cgi->param) { $error{$pkgpart} = $error if $error; } -my $classnum = $cgi->param('classnum'); +my $dest = $fsurl.'browse/part_pkg-fcc.html?'; +foreach (qw(classnum maxrecords offset)) { + if ( $cgi->param($_) =~ /^(\d+)$/ ) { + $dest .= "$_=$1;"; + } +} -my $jump = ''; if ( $cgi->param('jump') =~ /^pkgpart(\d+)$/ ) { - $jump = '#'.$1; + $dest .= "#$1"; } -- cgit v1.2.1 From a70498f14ae5d3be7f57ce81fef703b869ccdf0a Mon Sep 17 00:00:00 2001 From: Jonathan Prykop Date: Thu, 19 Feb 2015 15:05:07 -0600 Subject: RT#28246: Add more details to Change History for Discounts [better error handling] --- httemplate/elements/change_history_common.html | 2 ++ 1 file changed, 2 insertions(+) diff --git a/httemplate/elements/change_history_common.html b/httemplate/elements/change_history_common.html index 9fc85aa53..c858ec123 100644 --- a/httemplate/elements/change_history_common.html +++ b/httemplate/elements/change_history_common.html @@ -191,6 +191,8 @@ my %h_table_labelsub = ( my $discounts = {}; my $discount_descripsub = sub { my($item) = @_; + die "Could not find part_pkg for pkgpart " . $item->pkgpart + unless $item->part_pkg; $pkgpart{$item->pkgpart} ||= $item->part_pkg->pkg; my $dnum = $item->discountnum; $discounts->{$dnum} ||= qsearchs({ -- cgit v1.2.1 From 834b24e3a5aeb9188635e710be7002af04f187c8 Mon Sep 17 00:00:00 2001 From: Jonathan Prykop Date: Thu, 19 Feb 2015 15:34:47 -0600 Subject: RT#28246: Add more details to Change History for Discounts [actually fixed the bug] --- httemplate/elements/change_history_common.html | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/httemplate/elements/change_history_common.html b/httemplate/elements/change_history_common.html index c858ec123..2d2c4c0be 100644 --- a/httemplate/elements/change_history_common.html +++ b/httemplate/elements/change_history_common.html @@ -191,9 +191,10 @@ my %h_table_labelsub = ( my $discounts = {}; my $discount_descripsub = sub { my($item) = @_; - die "Could not find part_pkg for pkgpart " . $item->pkgpart - unless $item->part_pkg; - $pkgpart{$item->pkgpart} ||= $item->part_pkg->pkg; + $pkgpart{$item->pkgpart} ||= qsearchs({ + 'table' => 'part_pkg', + 'hashref' => {'pkgpart' => $item->pkgpart} + })->pkg; my $dnum = $item->discountnum; $discounts->{$dnum} ||= qsearchs({ 'table'=>'discount', -- cgit v1.2.1 From 4bbd2db7a016d9da19f1524895e3d04c3abf89a4 Mon Sep 17 00:00:00 2001 From: Jonathan Prykop Date: Fri, 20 Feb 2015 15:28:46 -0600 Subject: RT#23598: Feature Request - Email notice to A/R Report Results [now uses checkboxes and a proper popup] --- httemplate/elements/popup_link_onclick.html | 8 ++- httemplate/misc/email-customers.html | 16 +++++- httemplate/search/elements/checkbox-foot.html | 9 +++ .../search/elements/cust_main_dayranges.html | 65 +++++++++++++--------- httemplate/search/report_receivables.cgi | 2 +- 5 files changed, 68 insertions(+), 32 deletions(-) diff --git a/httemplate/elements/popup_link_onclick.html b/httemplate/elements/popup_link_onclick.html index 961f62336..5173115a5 100644 --- a/httemplate/elements/popup_link_onclick.html +++ b/httemplate/elements/popup_link_onclick.html @@ -8,6 +8,9 @@ Example: #required 'action' => 'content.html', # uri for content of popup + + #alternately, use instead of action + 'js_action' => 'url', # javascript variable or expression #strongly recommended 'actionlabel => 'You clicked', # popup title @@ -47,7 +50,8 @@ if (ref($_[0]) eq 'HASH') { $params = { @_ }; } -$action = $params->{'action'} if exists $params->{'action'}; +$action = q(') . $params->{'action'} . q(') if exists $params->{'action'}; +$action = $params->{'js_action'} if exists $params->{'js_action'}; $actionlabel = $params->{'actionlabel'} if exists $params->{'actionlabel'}; $width = $params->{'width'} if exists $params->{'width'}; $height = $params->{'height'} if exists $params->{'height'}; @@ -61,7 +65,7 @@ $scrolling = $params->{'scrolling'} if exists $params->{'scrolling'}; my $popup_name = 'popup-'.time. "-$$-". rand() * 2**32; my $onclick = - "overlib( OLiframeContent('$action', $width, $height, '$popup_name', 0, '$scrolling' ), ". + "overlib( OLiframeContent($action, $width, $height, '$popup_name', 0, '$scrolling' ), ". "CAPTION, '$actionlabel', STICKY, AUTOSTATUSCAP, MIDX, 0, MIDY, 0, ". "DRAGGABLE, CLOSECLICK, ". "BGCOLOR, '$color', CGCOLOR, '$color', CLOSETEXT, '$closetext'". diff --git a/httemplate/misc/email-customers.html b/httemplate/misc/email-customers.html index c74c15b1e..83e86158f 100644 --- a/httemplate/misc/email-customers.html +++ b/httemplate/misc/email-customers.html @@ -1,4 +1,9 @@ +% if ($popup) { +<% include('/elements/header-popup.html', $title) %> +% } else { <% include('/elements/header.html', $title) %> +% } + @@ -7,6 +12,8 @@ %# multi-valued search params. We are no longer in search context, so we %# pack the search into a Storable string for later use. + + % if ( $cgi->param('action') eq 'send' ) { @@ -16,7 +23,7 @@ 'OneTrueForm', [ qw( search table from subject html_body text_body msgnum ) ], 'process/email-customers.html', - { 'message' => "Notice sent" }, #would be nice to show #, but.. + $pdest, ) %> @@ -159,13 +166,18 @@ my $conf = FS::Conf->new; my $table = $cgi->param('table') or die "'table' required"; my $agent_virt_agentnum = $cgi->param('agent_virt_agentnum') || ''; +my $popup = $cgi->param('popup'); +my $url = $cgi->param('url'); +my $pdest = { 'message' => "Notice sent" }; +$pdest->{'url'} = $cgi->param('url') if $url; + my %search; if ( $cgi->param('search') ) { %search = %{ thaw(decode_base64($cgi->param('search'))) }; } else { %search = $cgi->Vars; - delete $search{$_} for qw( action table from subject html_body text_body ); + delete $search{$_} for qw( action table from subject html_body text_body popup url ); # FS::$table->search is expected to know which parameters might be # multi-valued, and to accept scalar values for them also. No good # solution to this since CGI can't tell whether a parameter _might_ diff --git a/httemplate/search/elements/checkbox-foot.html b/httemplate/search/elements/checkbox-foot.html index cc4bac69b..c47009425 100644 --- a/httemplate/search/elements/checkbox-foot.html +++ b/httemplate/search/elements/checkbox-foot.html @@ -75,6 +75,15 @@ function setAll(setTo) { checkboxes[i].checked = setTo; } } +function toCGIString() { + var out = ''; + for (var i = 0; i < checkboxes.length; i++) { + if (checkboxes[i].checked) { + out += '&' + checkboxes[i].name + '=' + checkboxes[i].value; + } + } + return out; +} <%init> my %opt = @_; diff --git a/httemplate/search/elements/cust_main_dayranges.html b/httemplate/search/elements/cust_main_dayranges.html index 73a429f8a..e5b1f478c 100644 --- a/httemplate/search/elements/cust_main_dayranges.html +++ b/httemplate/search/elements/cust_main_dayranges.html @@ -21,6 +21,7 @@ Example: 'query' => $sql_query, 'count_query' => $count_sql, 'header' => [ + @act_blank, @cust_header, '0-30', '30-60', @@ -28,9 +29,9 @@ Example: '90+', emt('Total'), @pay_head, - @act_header, ], 'footer' => [ + @act_blank, 'Total', ( map '',( 1 .. $#cust_header ),), sprintf( $money_char.'%.2f', @@ -44,9 +45,9 @@ Example: sprintf( ''.$money_char.'%.2f', $row->{'rangecol_0_0'} ), ('') x @pay_labels, - @act_blank, ], 'fields' => [ + @act_fields, FS::UI::Web::cust_fields_subs(), format_rangecol('0_30'), format_rangecol('30_60'), @@ -54,9 +55,9 @@ Example: format_rangecol('90_0'), format_rangecol('0_0'), @pay_labels, - @act_fields, ], 'links' => [ + @act_blank, ( map { $_ ne 'Cust. Status' ? $clink : '' } @cust_header ), @@ -66,44 +67,41 @@ Example: '', '', @pay_links, - @act_blank, ], - 'link_onclicks' => [ ( map '', @cust_header ), - '', '', '', '', '', - ( map '', @pay_labels ), - @act_link_onclicks, - ], - 'align' => FS::UI::Web::cust_aligns(). + 'align' => $act_align. + FS::UI::Web::cust_aligns(). 'rrrrr'. ('c' x @pay_labels), - @act_align, - 'size' => [ ( map '', @cust_header ), + 'size' => [ + @act_blank, + ( map '', @cust_header ), #'-1', '', '', '', '', '', ], - '', '', '', '', '', '', + '', '', '', '', '', ( map '', @pay_labels ), + ], + 'style' => [ @act_blank, - ], - 'style' => [ FS::UI::Web::cust_styles(), + FS::UI::Web::cust_styles(), #'b', '', '', '', '', 'b', ], '', '', '', '', 'b', ( map '', @pay_labels ), - @act_blank, ], - 'xls_format' => [ (map '', FS::UI::Web::cust_styles), - '', '', '', '', { bold => 1 }, + 'xls_format' => [ @act_blank, + (map '', FS::UI::Web::cust_styles), + '', '', '', '', { bold => 1 }, ], 'color' => [ + @act_blank, FS::UI::Web::cust_colors(), '', '', '', '', '', - '', ( map '', @pay_labels ), - @act_blank, ], + 'html_foot' => $html_foot, %opt, &> <%init> @@ -250,16 +248,29 @@ if($opt{'payment_links'} && $curuser->access_right('Process payment') && @payby) @payby ); } -my (@act_header, @act_fields, @act_link_onclicks, @act_align, @act_blank); -if (delete($opt{'email_links'})) { - push @act_header, 'Actions'; - push @act_fields, sub { 'send email' }; - push @act_link_onclicks, sub { +my (@act_blank, @act_fields, $act_align, $html_foot); +if (delete($opt{'email_checkboxes'})) { + my $email_link = q!var url = toCGIString(); !; + $email_link .= q/if (!url) { alert('No customers selected'); return false; }; /; + $email_link .= q!url = '!; + $email_link .= "${p}misc/email-customers.html?table=cust_main"; + $email_link .= q!' + url + '&popup=1&url=javascript%3Awindow.top.location.reload%28%29%3B'; !; + $email_link .= include('/elements/popup_link_onclick.html', + 'js_action' => 'url', + 'actionlabel' => 'Send Customer Email', + 'width' => '900', + 'height' => '500', + ); + $html_foot = include('checkbox-foot.html', + label => 'Email selected customers', + onclick => $email_link, + ); + push @act_fields, sub { my $row = shift; my $custnum = $row->custnum; - return qq!window.open('${p}misc/email-customers.html?table=cust_main&custnum=$custnum','_blank')!; + qq!!; }; - push @act_align, 'l'; + $act_align = 'l'; push @act_blank, ''; } diff --git a/httemplate/search/report_receivables.cgi b/httemplate/search/report_receivables.cgi index bca2a057a..adbbc859c 100755 --- a/httemplate/search/report_receivables.cgi +++ b/httemplate/search/report_receivables.cgi @@ -2,7 +2,7 @@ 'title' => emt('Accounts Receivable Aging Summary'), 'range_sub' => \&balance, 'payment_links' => 1, - 'email_links' => 1, + 'email_checkboxes' => 1, &> <%init> -- cgit v1.2.1 From 1ac6983f11ce30a2196ef5e44c051a34c776831f Mon Sep 17 00:00:00 2001 From: Mark Wells Date: Fri, 20 Feb 2015 14:40:16 -0800 Subject: unbreak projected future revenue query, #33599, fallout from #32472 --- FS/FS/Report/Table.pm | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/FS/FS/Report/Table.pm b/FS/FS/Report/Table.pm index 69686df9b..479747307 100644 --- a/FS/FS/Report/Table.pm +++ b/FS/FS/Report/Table.pm @@ -495,12 +495,17 @@ sub _cust_bill_pkg_recurring { my @where = ( '(pkgnum != 0 OR feepart IS NOT NULL)', - $self->with_classnum($opt{'classnum'}, $opt{'use_override'}), $self->with_report_option(%opt), $self->with_refnum(%opt), $self->with_cust_classnum(%opt) ); + my $where_classnum = $self->with_classnum($opt{'classnum'}, $opt{'use_override'}); + if ($opt{'project'}) { + $where_classnum =~ s/\bcust_bill_pkg/v_cust_bill_pkg/g; + } + push @where, $where_classnum; + if ( $opt{'distribute'} ) { $where[0] = 'pkgnum != 0'; # specifically exclude fees push @where, "cust_main.agentnum = $agentnum" if $agentnum; -- cgit v1.2.1 From 56135d254ea247875ff0a3775a94dddb9ceb0490 Mon Sep 17 00:00:00 2001 From: Jonathan Prykop Date: Fri, 20 Feb 2015 19:24:27 -0600 Subject: RT#23741 Multiple payment options [quick fallout fix] --- FS/FS/part_event/Condition/has_cust_payby_auto.pm | 1 + 1 file changed, 1 insertion(+) diff --git a/FS/FS/part_event/Condition/has_cust_payby_auto.pm b/FS/FS/part_event/Condition/has_cust_payby_auto.pm index edfb7eccb..dce97df8f 100644 --- a/FS/FS/part_event/Condition/has_cust_payby_auto.pm +++ b/FS/FS/part_event/Condition/has_cust_payby_auto.pm @@ -3,6 +3,7 @@ package FS::part_event::Condition::has_cust_payby_auto; use strict; use Tie::IxHash; use FS::payby; +use FS::Record qw(qsearch); use base qw( FS::part_event::Condition ); -- cgit v1.2.1 From 49deddfdc5f60c5cde01a5152e6bae858ed8e72a Mon Sep 17 00:00:00 2001 From: Jonathan Prykop Date: Fri, 20 Feb 2015 20:07:18 -0600 Subject: RT#14671: Usage for current day when billing outstanding usage (for cancelling customers) [now uses suspend for everything] --- FS/FS/cust_pkg.pm | 32 +++++++++++++++++--------- httemplate/view/cust_main/packages/status.html | 12 +++++++--- 2 files changed, 30 insertions(+), 14 deletions(-) diff --git a/FS/FS/cust_pkg.pm b/FS/FS/cust_pkg.pm index fb3b0ff80..b64d4dc38 100644 --- a/FS/FS/cust_pkg.pm +++ b/FS/FS/cust_pkg.pm @@ -784,6 +784,10 @@ to a different pkgpart or location, and probably shouldn't be in any other case. If it's not set, the 'unused_credit_cancel' part_pkg option will be used. +=item delay_cancel - for internal use, to allow proper handling of +supplemental packages when the main package is flagged to suspend +before cancelling + =back If there is an error, returns the error, otherwise returns false. @@ -823,7 +827,7 @@ sub cancel { my $date = $options{'date'} if $options{'date'}; # expire/cancel later $date = '' if ($date && $date <= $cancel_time); # complain instead? - my $delay_cancel = undef; + my $delay_cancel = $options{'delay_cancel'}; if ( !$date && $self->part_pkg->option('delay_cancel',1) && (($self->status eq 'active') || ($self->status eq 'suspended')) ) { @@ -907,7 +911,7 @@ sub cancel { if ( $date ) { $hash{'expire'} = $date; if ($delay_cancel) { - $hash{'susp'} = $cancel_time unless $self->susp; + # just to be sure these are clear $hash{'adjourn'} = undef; $hash{'resume'} = undef; } @@ -934,21 +938,24 @@ sub cancel { } foreach my $supp_pkg ( $self->supplemental_pkgs ) { - if ($delay_cancel) { - $error = $supp_pkg->suspend( - 'from_main' => 1, - 'from_cancel' => 1, - 'time' => $cancel_time - ); - } else { - $error = $supp_pkg->cancel(%options, 'from_main' => 1); - } + $error = $supp_pkg->cancel(%options, + 'from_main' => 1, + 'date' => $date, #in case it got changed by delay_cancel + 'delay_cancel' => $delay_cancel, + ); if ( $error ) { $dbh->rollback if $oldAutoCommit; return "canceling supplemental pkg#".$supp_pkg->pkgnum.": $error"; } } + if ($delay_cancel && !$options{'from_main'}) { + $error = $new->suspend( + 'from_cancel' => 1, + 'time' => $cancel_time + ); + } + unless ($date) { foreach my $usage ( $self->cust_pkg_usage ) { $error = $usage->delete; @@ -3391,6 +3398,9 @@ really the whole point of the delay_cancel option. sub is_status_delay_cancel { my ($self) = @_; + if ( $self->main_pkgnum and $self->pkglinknum ) { + return $self->main_pkg->is_status_delay_cancel; + } return 0 unless $self->part_pkg->option('delay_cancel',1); return 0 unless $self->status eq 'suspended'; return 0 unless $self->expire; diff --git a/httemplate/view/cust_main/packages/status.html b/httemplate/view/cust_main/packages/status.html index f760d6fcc..36419646c 100644 --- a/httemplate/view/cust_main/packages/status.html +++ b/httemplate/view/cust_main/packages/status.html @@ -54,9 +54,15 @@ <% pkg_status_row( $cust_pkg, emt('On Hold'), '', 'color'=>'7E0079', %opt ) %> % } else { #status: suspended - - <% pkg_status_row( $cust_pkg, emt('Suspended'), 'susp', 'color'=>'FF9900', %opt ) %> -% my $cpr = $cust_pkg->last_cust_pkg_reason('susp'); +% my ($cpr,$susplabel); +% if ($cust_pkg->is_status_delay_cancel) { +% $cpr = $cust_pkg->last_cust_pkg_reason('expire'); +% $susplabel = 'Suspended (Cancelled)'; +% } else { +% $cpr = $cust_pkg->last_cust_pkg_reason('susp'); +% $susplabel = 'Suspended'; +% } + <% pkg_status_row( $cust_pkg, emt($susplabel), 'susp', 'color'=>'FF9900', %opt ) %> <% pkg_reason_row( $cust_pkg, $cpr, 'color' => 'FF9900', %opt ) %> % } -- cgit v1.2.1