From c2ee6c5c4f274bbf86729cacd2fe011ea71f725d Mon Sep 17 00:00:00 2001 From: Mark Wells Date: Sat, 31 Mar 2012 17:56:52 -0700 Subject: add customer referrals to signup graph, #17050 --- FS/FS/Report/Table.pm | 21 ++++++++++++++++----- httemplate/graph/cust_signup.html | 29 +++++++++++++++++++---------- httemplate/graph/report_cust_signup.html | 6 ++++++ 3 files changed, 41 insertions(+), 15 deletions(-) diff --git a/FS/FS/Report/Table.pm b/FS/FS/Report/Table.pm index 3942543b5..b0e911f84 100644 --- a/FS/FS/Report/Table.pm +++ b/FS/FS/Report/Table.pm @@ -32,21 +32,32 @@ options in %opt. =over 4 -=item signups: The number of customers signed up. +=item signups: The number of customers signed up. Options are "refnum" +(limit by advertising source) and "indirect" (boolean, tells us to limit +to customers that have a referral_custnum that matches the advertising source). =cut sub signups { my( $self, $speriod, $eperiod, $agentnum, %opt ) = @_; - my @where = ( - $self->in_time_period_and_agent($speriod, $eperiod, $agentnum, 'signupdate') + my @where = ( $self->in_time_period_and_agent($speriod, $eperiod, $agentnum, + 'cust_main.signupdate') ); - if ( $opt{'refnum'} ) { + my $join = ''; + if ( $opt{'indirect'} ) { + $join = " JOIN cust_main AS referring_cust_main". + " ON (cust_main.referral_custnum = referring_cust_main.custnum)"; + + if ( $opt{'refnum'} ) { + push @where, "referring_cust_main.refnum = ".$opt{'refnum'}; + } + } + elsif ( $opt{'refnum'} ) { push @where, "refnum = ".$opt{'refnum'}; } $self->scalar_sql( - "SELECT COUNT(*) FROM cust_main WHERE ".join(' AND ', @where) + "SELECT COUNT(*) FROM cust_main $join WHERE ".join(' AND ', @where) ); } diff --git a/httemplate/graph/cust_signup.html b/httemplate/graph/cust_signup.html index dd9100f1e..a3eb702f2 100644 --- a/httemplate/graph/cust_signup.html +++ b/httemplate/graph/cust_signup.html @@ -9,7 +9,7 @@ 'agentnum' => $agentnum, 'sprintf' => '%u', 'disable_money' => 1, - 'bottom_total' => (scalar @items > 1 ? 1 : 0), + 'bottom_total' => (scalar @items > 1 && !$indirect ? 1 : 0), 'bottom_link' => $bottom_link, 'link_fromparam' => 'signupdate_begin', 'link_toparam' => 'signupdate_end', @@ -59,25 +59,34 @@ elsif ( $cgi->param('refnum') =~ /^(\d*)$/ ) { } } +my $indirect = ($cgi->param('indirect') eq 'Y' ? 1 : 0); + my (@items, @labels, @colors, @params, @links); my $hue = 0; -my $hue_increment = 125; +my $hue_increment = 75; my @signup_colors; foreach my $referral (@referral) { + my %params = ('refnum' => $referral->refnum) unless $all_referral; + push @items, 'signups'; push @labels, ( $all_referral ? 'Signups' : $referral->referral ); - push @params, ( $all_referral ? [] : [ 'refnum' => $referral->refnum ] ); + push @params, [ %params ]; push @links, $link . ($all_referral ? '' : "refnum=".$referral->refnum.';'); - if ( !@signup_colors ) { - @signup_colors = Color::Scheme->new - ->from_hue($hue) - ->scheme('analogic') - ->colors; - $hue += $hue_increment; + # rotate hue for each referral type + @signup_colors = Color::Scheme->new->from_hue($hue)->colors; + $hue += $hue_increment; + push @colors, $signup_colors[0]; + if ( $indirect ) { + push @items, 'signups'; + push @labels, $all_referral ? + 'Referrals' : + $referral->referral . ' referrals'; + push @params, [ %params, 'indirect' => 1 ]; + push @links, ''; + push @colors, $signup_colors[1]; } - push @colors, shift @signup_colors; } diff --git a/httemplate/graph/report_cust_signup.html b/httemplate/graph/report_cust_signup.html index 9d3f5006b..12dec8e6a 100644 --- a/httemplate/graph/report_cust_signup.html +++ b/httemplate/graph/report_cust_signup.html @@ -22,6 +22,12 @@ ) %> +<& /elements/tr-td-label.html, label => 'Show customer referrals' &> + + + + +
-- cgit v1.2.1 From 59db9d8aa66fe128a26e512c5172982e041c59ae Mon Sep 17 00:00:00 2001 From: Ivan Kohler Date: Sun, 1 Apr 2012 11:07:12 -0700 Subject: 3.0 --- httemplate/docs/about.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/httemplate/docs/about.html b/httemplate/docs/about.html index f0994e506..76a477c05 100644 --- a/httemplate/docs/about.html +++ b/httemplate/docs/about.html @@ -8,7 +8,7 @@
-© 2011 Freeside Internet Services, Inc.
+© 2012 Freeside Internet Services, Inc.
All rights reserved.
Licensed under the terms of the
GNU Affero General Public License.
@@ -29,7 +29,7 @@ GNU Affero General Public License.

-"The sky was yellow and the sun was blue" -R. Hunter +"A selfish heart is trouble, but a foolish heart is worse" -R. Hunter
<& /elements/tr-td-label.html, label => ($opt{'label'} || 'Router') &> @@ -27,7 +38,7 @@ function lock_ip_addr(obj, i) { records => \@routers, name_col => 'routername', value_col => 'routernum', - onchange => 'lock_ip_addr', + onchange => 'update_ip_addr', curr_value=> $opt{'routernum'}, }, { @@ -39,6 +50,7 @@ function lock_ip_addr(obj, i) { name_col => 'cidr', link_col => 'routernum', empty_label => '(any)', + onchange => 'update_ip_addr', curr_value => $opt{'blocknum'}, }, ] @@ -52,12 +64,11 @@ function lock_ip_addr(obj, i) { % } % else { + value="<% $opt{'ip_addr'} |h%>" onfocus="clearhint_ip_addr(this)"> % } - <%init> -- cgit v1.2.1 From b17ce7c641ad897ec35cac0c8f8e69320c19ab0e Mon Sep 17 00:00:00 2001 From: Ivan Kohler Date: Thu, 12 Apr 2012 15:13:49 -0700 Subject: adding quick package definition bulk change tool, RT#17348 --- bin/part_pkg-bulk_change | 72 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100755 bin/part_pkg-bulk_change diff --git a/bin/part_pkg-bulk_change b/bin/part_pkg-bulk_change new file mode 100755 index 000000000..aecfea580 --- /dev/null +++ b/bin/part_pkg-bulk_change @@ -0,0 +1,72 @@ +#!/usr/bin/perl + +use strict; +use vars qw( $opt_r $opt_o $opt_v ); +use Getopt::Std; +use FS::UID qw(adminsuidsetup); +use FS::Record qw(qsearch qsearchs); +use FS::part_pkg; +use FS::part_pkg_option; + +getopts('ro:v:'); + +my $user = shift or &usage; +adminsuidsetup $user; + +foreach my $part_pkg ( qsearch('part_pkg', {}) ) { + next if ! $part_pkg->freq && $opt_r; + + my %hash = ( + 'pkgpart' => $part_pkg->pkgpart, + 'optionname' => $opt_o, + ); + + my $part_pkg_option = qsearchs('part_pkg_option', \%hash); + + if ( $part_pkg_option ) { + next if $part_pkg_option->optionvalue eq $opt_v; + $part_pkg_option->optionvalue($opt_v); + my $error = $part_pkg_option->replace; + die $error if $error; + } else { + $part_pkg_option = new FS::part_pkg_option { %hash, 'optionvalue'=>$opt_v }; + my $error = $part_pkg_option->insert; + die $error if $error; + } + +} + +sub usage { + die "usage: part_pkg-bulk_change [ -r ] -o option_name -v option_value employee_username\n"; +} + +=head1 NAME + +cust_main-bulk_change + +=head1 SYNOPSIS + + part_pkg-bulk_change [ -r ] -o option_name -v option_value employee_username + +=head1 DESCRIPTION + +Command-line tool to change the payby field for a group of customers. + +-r: recurring package definitions only + +-o: part_pkg_option optionname + +-v: part_pkg_option optionvalue + +employee_username + +=head1 BUGS + +=head1 SEE ALSO + +L + +=cut + +1; + -- cgit v1.2.1 From c683be2e0bc89b9d11dfd5454a6cd21161b752ef Mon Sep 17 00:00:00 2001 From: Ivan Kohler Date: Thu, 12 Apr 2012 16:13:07 -0700 Subject: fix voiding of APPL and ANRD payments, RT#17344 --- FS/FS/cust_pay_void.pm | 30 ++---------------------------- 1 file changed, 2 insertions(+), 28 deletions(-) diff --git a/FS/FS/cust_pay_void.pm b/FS/FS/cust_pay_void.pm index f1193cd24..bebcfd4cc 100644 --- a/FS/FS/cust_pay_void.pm +++ b/FS/FS/cust_pay_void.pm @@ -68,9 +68,7 @@ order taker (see L) =item payby -`CARD' (credit cards), `CHEK' (electronic check/ACH), -`LECB' (phone bill billing), `BILL' (billing), `CASH' (cash), -`WEST' (Western Union), `MCRD' (Manual credit card), or `COMP' (free) +Payment Type (See L for valid values) =item payinfo @@ -186,6 +184,7 @@ sub check { || $self->ut_foreign_keyn('pkgnum', 'cust_pkg', 'pkgnum') || $self->ut_numbern('void_date') || $self->ut_textn('reason') + || $self->payinfo_check ; return $error if $error; @@ -197,31 +196,6 @@ sub check { $self->void_date(time) unless $self->void_date; - $self->payby =~ /^(CARD|CHEK|LECB|BILL|COMP|PREP|CASH|WEST|MCRD)$/ - or return "Illegal payby"; - $self->payby($1); - - #false laziness with cust_refund::check - if ( $self->payby eq 'CARD' ) { - my $payinfo = $self->payinfo; - $payinfo =~ s/\D//g; - $self->payinfo($payinfo); - if ( $self->payinfo ) { - $self->payinfo =~ /^(\d{13,16}|\d{8,9})$/ - or return "Illegal (mistyped?) credit card number (payinfo)"; - $self->payinfo($1); - validate($self->payinfo) or return "Illegal credit card number"; - return "Unknown card type" if $self->payinfo !~ /^99\d{14}$/ #token - && cardtype($self->payinfo) eq "Unknown"; - } else { - $self->payinfo('N/A'); - } - - } else { - $error = $self->ut_textn('payinfo'); - return $error if $error; - } - $self->void_usernum($FS::CurrentUser::CurrentUser->usernum) unless $self->void_usernum; -- cgit v1.2.1 From 3ccf7174fccb0b576a8c34838b3db4a429635483 Mon Sep 17 00:00:00 2001 From: Ivan Kohler Date: Thu, 12 Apr 2012 16:14:23 -0700 Subject: display apple and android store payments by name --- FS/FS/payby.pm | 5 +++++ httemplate/view/cust_main/payment_history.html | 8 +++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/FS/FS/payby.pm b/FS/FS/payby.pm index 33ed42507..d1961a58d 100644 --- a/FS/FS/payby.pm +++ b/FS/FS/payby.pm @@ -176,6 +176,11 @@ sub realtime { # can use realtime payment facilities return $hash{$payby}->{realtime}; } +sub payby2shortname { + my $self = shift; + map { $_ => $hash{$_}->{shortname} } $self->payby; +} + sub payby2longname { my $self = shift; map { $_ => $hash{$_}->{longname} } $self->payby; diff --git a/httemplate/view/cust_main/payment_history.html b/httemplate/view/cust_main/payment_history.html index c453ffadc..c7a7c8024 100644 --- a/httemplate/view/cust_main/payment_history.html +++ b/httemplate/view/cust_main/payment_history.html @@ -500,14 +500,15 @@ foreach my $cust_refund ($cust_main->cust_refund) { sub translate_payby { my ($payby,$payinfo) = (shift,shift); my %payby = ( + FS::payby->payby2shortname, BILL => $payinfo ? emt('Check #') : '', CHEK => emt('Electronic check '), PREP => emt('Prepaid card '), CARD => emt('Credit card #'), COMP => emt('Complimentary by '), - CASH => emt('Cash'), - WEST => emt('Western Union'), - MCRD => emt('Manual credit card'), + #CASH => emt('Cash'), + #WEST => emt('Western Union'), + #MCRD => emt('Manual credit card'), ); $payby = (exists $payby{$payby}) ? $payby{$payby} : $payby; $payby; @@ -516,6 +517,7 @@ sub translate_payby { sub translate_payby_refund { my ($payby,$payinfo) = (shift,shift); my %payby = ( + FS::payby->payby2shortname, BILL => $payinfo ? emt('Check #') : emt('Check'), CHEK => emt('Electronic check '), CARD => emt('Credit card #'), -- cgit v1.2.1 From 217bd576f8024ea541bdbb967e1c53f242980e61 Mon Sep 17 00:00:00 2001 From: Ivan Kohler Date: Thu, 12 Apr 2012 20:16:38 -0700 Subject: add cust_bill-line_item-date_description, RT#15858 --- FS/FS/Conf.pm | 14 ++++++++++++-- FS/FS/cust_bill.pm | 14 +++++++++++++- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/FS/FS/Conf.pm b/FS/FS/Conf.pm index d342e744d..80c034890 100644 --- a/FS/FS/Conf.pm +++ b/FS/FS/Conf.pm @@ -3602,9 +3602,19 @@ and customer address. Include units.', 'section' => 'billing', 'description' => 'Display format for line item date ranges on invoice line items.', 'type' => 'select', - 'select_hash' => [ '' => 'STARTDATE-ENDDATE', - 'month_of' => 'Month of MONTHNAME', + 'select_hash' => [ '' => 'STARTDATE-ENDDATE', + 'month_of' => 'Month of MONTHNAME', + 'X_month' => 'DATE_DESC MONTHNAME', ], + 'per_agent' => 1, + }, + + { + 'key' => 'cust_bill-line_item-date_description', + 'section' => 'billing', + 'description' => 'Text to display for "DATE_DESC" when using cust_bill-line_item-date_style DATE_DESC MONTHNAME.', + 'type' => 'text', + 'per_agent' => 1, }, { diff --git a/FS/FS/cust_bill.pm b/FS/FS/cust_bill.pm index 255ce6009..a76170a9b 100644 --- a/FS/FS/cust_bill.pm +++ b/FS/FS/cust_bill.pm @@ -4887,6 +4887,8 @@ sub _items_cust_bill_pkg { my $maxlength = $conf->config('cust_bill-latex_lineitem_maxlength') || 50; + my $cust_main = $self->cust_main;#for per-agent cust_bill-line_item-ate_style + my @b = (); my ($s, $r, $u) = ( undef, undef, undef ); foreach my $cust_bill_pkg ( @$cust_bill_pkgs ) @@ -5022,14 +5024,24 @@ sub _items_cust_bill_pkg { my $description = ($is_summary && $type && $type eq 'U') ? "Usage charges" : $desc; + #pry be a bit more efficient to look some of this conf stuff up + # outside the loop unless ( $conf->exists('disable_line_item_date_ranges') || $cust_pkg->part_pkg->option('disable_line_item_date_ranges',1) ) { my $time_period; - my $date_style = $conf->config('cust_bill-line_item-date_style'); + my $date_style = $conf->config( 'cust_bill-line_item-date_style', + $cust_main->agentnum + ); if ( defined($date_style) && $date_style eq 'month_of' ) { $time_period = time2str('The month of %B', $cust_bill_pkg->sdate); + } elsif ( defined($date_style) && $date_style eq 'X_month' ) { + my $desc = $conf->config( 'cust_bill-line_item-date_description', + $cust_main->agentnum + ); + $desc .= ' ' unless $desc =~ /\s$/; + $time_period = $desc. time2str('%B', $cust_bill_pkg->sdate); } else { $time_period = time2str($date_format, $cust_bill_pkg->sdate). " - ". time2str($date_format, $cust_bill_pkg->edate); -- cgit v1.2.1 From 18459c4369f63b7fda11a3ff7a0af067bed0c9bf Mon Sep 17 00:00:00 2001 From: Mark Wells Date: Fri, 13 Apr 2012 12:08:40 -0700 Subject: adjustment to display_custnum special format, #16815 --- FS/FS/Conf.pm | 3 ++- FS/FS/cust_main.pm | 11 +++++++++-- FS/FS/cust_main/Search.pm | 36 ++++++++++++++++++++---------------- 3 files changed, 31 insertions(+), 19 deletions(-) diff --git a/FS/FS/Conf.pm b/FS/FS/Conf.pm index 80c034890..edfe3c27a 100644 --- a/FS/FS/Conf.pm +++ b/FS/FS/Conf.pm @@ -3889,7 +3889,7 @@ and customer address. Include units.', 'section' => 'UI', 'description' => 'Prefix the customer number with this string for display purposes.', 'type' => 'text', - #and then probably agent-virt this to merge these instances + 'per_agent' => 1, }, { @@ -3898,6 +3898,7 @@ and customer address. Include units.', 'description' => 'Use this customer number prefix format', 'type' => 'select', 'select_hash' => [ '' => '', + 'CoStAg' => 'CoStAg (country, state, agent name or display_prefix)', 'CoStCl' => 'CoStCl (country, state, class name)' ], }, diff --git a/FS/FS/cust_main.pm b/FS/FS/cust_main.pm index 1e0e6d3b1..845d09848 100644 --- a/FS/FS/cust_main.pm +++ b/FS/FS/cust_main.pm @@ -3963,9 +3963,16 @@ cust_main-default_agent_custid is set and it has a value, custnum otherwise. sub display_custnum { my $self = shift; - my $prefix = $conf->config('cust_main-custnum-display_prefix') || ''; + my $prefix = $conf->config('cust_main-custnum-display_prefix', $self->agentnum) || ''; if ( my $special = $conf->config('cust_main-custnum-display_special') ) { - if ( $special eq 'CoStCl' ) { + if ( $special eq 'CoStAg' ) { + $prefix = uc( join('', + $self->country, + ($self->state =~ /^(..)/), + $prefix || ($self->agent->agent =~ /^(..)/) + ) ); + } + elsif ( $special eq 'CoStCl' ) { $prefix = uc( join('', $self->country, ($self->state =~ /^(..)/), diff --git a/FS/FS/cust_main/Search.pm b/FS/FS/cust_main/Search.pm index 62464e4aa..1e9eee79d 100644 --- a/FS/FS/cust_main/Search.pm +++ b/FS/FS/cust_main/Search.pm @@ -127,6 +127,12 @@ sub smart_search { || ( $conf->config('cust_main-agent_custid-format') eq 'ww?d+' && $search =~ /^\s*(\w\w?\d+)\s*$/ ) + || ( $conf->config('cust_main-custnum-display_special') + # it's not currently possible for special prefixes to contain + # digits, so just strip off any alphabetic prefix and match + # the rest to custnum + && $search =~ /^\s*[[:alpha:]]*(\d+)\s*$/ + ) || ( $conf->exists('address1-search' ) && $search =~ /^\s*(\d+\-?\w*)\s*$/ #i.e. 1234A or 9432-D ) @@ -143,25 +149,23 @@ sub smart_search { } ); } - #if this becomes agent-virt need to get a list of all prefixes the current - #user can see (via their agents) - my $prefix = $conf->config('cust_main-custnum-display_prefix'); - if ( $prefix && $prefix eq substr($num, 0, length($prefix)) ) { - push @cust_main, qsearch( { - 'table' => 'cust_main', - 'hashref' => { 'custnum' => 0 + substr($num, length($prefix)), - %options, + # for all agents this user can see, if any of them have custnum prefixes + # that match the search string, include customers that match the rest + # of the custnum and belong to that agent + foreach my $agentnum ( $FS::CurrentUser::CurrentUser->agentnums ) { + my $p = $conf->config('cust_main-custnum-display_prefix', $agentnum); + next if !$p; + if ( $p eq substr($num, 0, length($p)) ) { + push @cust_main, qsearch( { + 'table' => 'cust_main', + 'hashref' => { 'custnum' => 0 + substr($num, length($p)), + 'agentnum' => $agentnum, + %options, }, - 'extra_sql' => " AND $agentnums_sql", #agent virtualization - } ); + } ); + } } - push @cust_main, qsearch( { - 'table' => 'cust_main', - 'hashref' => { 'agent_custid' => $num, %options }, - 'extra_sql' => " AND $agentnums_sql", #agent virtualization - } ); - if ( $conf->exists('address1-search') ) { my $len = length($num); $num = lc($num); -- cgit v1.2.1 From 2c1bad9f29492546788aa4ffa0baf8e1dc0fff58 Mon Sep 17 00:00:00 2001 From: Ivan Kohler Date: Fri, 13 Apr 2012 18:35:24 -0700 Subject: style ticket tab --- httemplate/elements/freeside.css | 28 ++++++++++++++++++++++++++++ httemplate/elements/table-grid.html | 13 +------------ httemplate/view/cust_main.cgi | 4 ++-- httemplate/view/cust_main/tickets.html | 9 +++++---- 4 files changed, 36 insertions(+), 18 deletions(-) diff --git a/httemplate/elements/freeside.css b/httemplate/elements/freeside.css index 44a4a3ca2..c291e1e33 100644 --- a/httemplate/elements/freeside.css +++ b/httemplate/elements/freeside.css @@ -250,3 +250,31 @@ div.fstabcontainer { background-color:#f8f8f8; } +table.grid { + border: 1px solid #cccccc; + -moz-box-shadow: 1px 1px 2px #666666; + -webkit-box-shadow: 1px 1px 2px #666666; + box-shadow: 1px 1px 2px #666666; + filter: progid:DXImageTransform.Microsoft.Shadow(color='#666666', Direction=135, Strength=2); +} + +th.grid { + padding-left: 3px; + padding-right: 3px; + padding-bottom: 2px; + border: none; + empty-cells: show; +} + +td.grid { + padding-left: 3px; + padding-right: 3px; + padding-bottom: 2px; + border: none; + empty-cells: show; +} + +table.inv { border: none } +th.inv { border: none } +td.inv { border: none } + diff --git a/httemplate/elements/table-grid.html b/httemplate/elements/table-grid.html index 4d7deeaa4..4f4200570 100644 --- a/httemplate/elements/table-grid.html +++ b/httemplate/elements/table-grid.html @@ -1,15 +1,4 @@ - - - CELLPADDING=<% $opt{cellpadding} %> <% $opt{bgcolor} %> STYLE="border: 1px solid #cccccc;"> +
CELLPADDING=<% $opt{cellpadding} %> <% $opt{bgcolor} %>> <%init> diff --git a/httemplate/view/cust_main.cgi b/httemplate/view/cust_main.cgi index fda4db0d9..9ce55b0b9 100755 --- a/httemplate/view/cust_main.cgi +++ b/httemplate/view/cust_main.cgi @@ -232,9 +232,9 @@ function areyousure(href, message) { % } % if ( $view eq 'jumbo' ) { -

- <% mt('Tickets') |h %>
+
% } +
% if ( $view eq 'tickets' || $view eq 'jumbo' ) { diff --git a/httemplate/view/cust_main/tickets.html b/httemplate/view/cust_main/tickets.html index adfaead6e..194e90742 100644 --- a/httemplate/view/cust_main/tickets.html +++ b/httemplate/view/cust_main/tickets.html @@ -9,6 +9,7 @@ function updateTicketLink() { keys %new_param),'Queue=') %>" + selector.options[selector.selectedIndex].value; } +Tickets<% mt('Create new ticket') |h %> <% mt('in queue') |h %> %# fetch list of queues in which the user can create tickets @@ -28,12 +29,12 @@ function updateTicketLink() { % } + | +View +<% mt($openlabel) |h %> | +<% mt('resolved') |h %>
-(<% mt("View $openlabel tickets for this customer") |h %>) -(<% mt('View resolved tickets for this customer') |h %>) -

- <& /elements/table-grid.html &> % my $bgcolor1 = '#eeeeee'; % my $bgcolor2 = '#ffffff'; -- cgit v1.2.1 From 33013bb1ef0b5f07105fe13f5bfc06350fc4d868 Mon Sep 17 00:00:00 2001 From: Ivan Kohler Date: Fri, 13 Apr 2012 19:17:06 -0700 Subject: fix "Use of uninitialized valud $driver name in pattern match (m//) at /usr/local/share/perl/5.10.1/FS/part_event/Condition.pm" warnings, cust_bill_has_service and has_cust_tag conditions under MySQL, fallout from RT#17035 --- FS/FS/part_event/Condition.pm | 4 ++-- FS/FS/part_event/Condition/cust_bill_has_service.pm | 4 +--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/FS/FS/part_event/Condition.pm b/FS/FS/part_event/Condition.pm index b3948153e..fc69f1d0c 100644 --- a/FS/FS/part_event/Condition.pm +++ b/FS/FS/part_event/Condition.pm @@ -363,7 +363,7 @@ sub condition_sql_option_option { #used for part_event/Condition/cust_bill_has_service.pm and has_cust_tag.pm #a little false laziness w/above and condition_sql_option_integer sub condition_sql_option_option_integer { - my( $class, $option, $driver_name ) = @_; + my( $class, $option ) = @_; ( my $condname = $class ) =~ s/^.*:://; @@ -375,7 +375,7 @@ sub condition_sql_option_option_integer { AND part_event_condition_option.optionvalue = 'HASH' )"; - my $integer = ($driver_name =~ /^mysql/) ? 'UNSIGNED INTEGER' : 'INTEGER'; + my $integer = (driver_name =~ /^mysql/) ? 'UNSIGNED INTEGER' : 'INTEGER'; my $optionname = "CAST(optionname AS $integer)"; diff --git a/FS/FS/part_event/Condition/cust_bill_has_service.pm b/FS/FS/part_event/Condition/cust_bill_has_service.pm index 65c996437..6e981ee03 100644 --- a/FS/FS/part_event/Condition/cust_bill_has_service.pm +++ b/FS/FS/part_event/Condition/cust_bill_has_service.pm @@ -42,9 +42,7 @@ sub condition_sql { my( $class, $table, %opt ) = @_; my $servicenums = - $class->condition_sql_option_option_integer( 'has_service', - $opt{'driver_name'}, - ); + $class->condition_sql_option_option_integer('has_service'); my $sql = qq| 0 < ( SELECT COUNT(cs.svcpart) FROM cust_bill_pkg cbp, cust_svc cs -- cgit v1.2.1 From 401ba3ab0637de1bc460370949b75dca092375d8 Mon Sep 17 00:00:00 2001 From: Mark Wells Date: Sat, 14 Apr 2012 11:43:08 -0700 Subject: fix various quick payment entry problems, #17356 --- httemplate/elements/customer-table.html | 298 +++++++++++---------- httemplate/misc/batch-cust_pay.html | 24 +- httemplate/misc/process/batch-cust_pay.cgi | 2 +- .../misc/xmlhttp-cust_main-discount_terms.cgi | 19 +- httemplate/misc/xmlhttp-cust_main-search.cgi | 8 +- 5 files changed, 182 insertions(+), 169 deletions(-) diff --git a/httemplate/elements/customer-table.html b/httemplate/elements/customer-table.html index aa085c41a..a517ece2a 100644 --- a/httemplate/elements/customer-table.html +++ b/httemplate/elements/customer-table.html @@ -67,7 +67,45 @@ Example: this.value = ''; } - + + function update_customer(searchrow, customerArray) { + + var custnum_obj = document.getElementById('custnum'+searchrow); + var customer = document.getElementById('customer'+searchrow); + var customer_select = document.getElementById('cust_select'+searchrow); + + custnum_obj.disabled = false; + custnum_obj.style.backgroundColor = '#ffffff'; + customer.disabled = false; + customer.style.backgroundColor = '#ffffff'; + + if ( customerArray.length == 0 ) { + + custnum_obj.value = 'Not found'; + customer.value = 'Not found'; + custnum_obj.style.color = '#ff0000'; + customer.style.color = '#ff0000'; + + customer.style.display = ''; + customer_select.style.display = 'none'; + return false; + + } else if ( customerArray.length == 5 ) { + + custnum_obj.value = customerArray[0]; + custnum_obj.style.color = '#000000'; + customer.value = customerArray[1]; + + update_balance_text(searchrow, customerArray[2]); + update_status_text( searchrow, customerArray[3]); + update_status_color(searchrow, '#'+customerArray[4]); + + customer.style.display = ''; + customer_select.style.display = 'none'; + return true; + } + } + function <% $opt{prefix} %>search_invnum() { this.style.color = '#000000' @@ -99,55 +137,25 @@ Example: customer_select.style.display = 'none'; var custnum_obj = document.getElementById('custnum'+searchrow); - var balance = document.getElementById('balance'+searchrow); - var status = document.getElementById('status'+searchrow); - balance.innerHTML = ''; - status.innerHTML = ''; + update_balance_text(searchrow, ''); + update_status_text(searchrow, ''); + update_status_color(searchrow, '#000000'); function search_invnum_update(customers) { var customerArray = eval('(' + customers + ')'); - - custnum_obj.disabled = false; - custnum_obj.style.backgroundColor = '#ffffff'; - customer.disabled = false; - customer.style.backgroundColor = '#ffffff'; - - if ( customerArray.length == 0 ) { - - custnum_obj.value = 'Not found'; - customer.value = 'Not found'; - custnum_obj.style.color = '#ff0000'; - customer.style.color = '#ff0000'; - - customer.style.display = ''; - customer_select.style.display = 'none'; - - } else if ( customerArray.length == 5 ) { - - custnum_obj.value = customerArray[0]; - custnum_obj.style.color = '#000000'; - customer.value = customerArray[1]; - balance.innerHTML = '<% $money_char %>' + customerArray[2] + '   '; - status.innerHTML = customerArray[3]; - status.style.color = '#'+customerArray[4]; - - customer.style.display = ''; - customer_select.style.display = 'none'; + update_customer(searchrow, customerArray); % if ( $opt{invnum_update_callback} ) { <% $opt{invnum_update_callback} %>(searchrow, '<% $opt{prefix} %>') % } - } - } invnum_search( invnum, search_invnum_update ); } - function <% $opt{prefix} %>search_custnum() { this.style.color = '#000000' @@ -180,42 +188,19 @@ Example: var invnum = document.getElementById('invnum'+searchrow); invnum.value = ''; - - var balance = document.getElementById('balance'+searchrow); - balance.innerHTML = ''; - - var status = document.getElementById('status'+searchrow); - status.innerHTML = ''; - function search_custnum_update(customers) { - - var customerArray = eval('(' + customers + ')'); + update_balance_text(searchrow, ''); + update_status_text( searchrow, ''); + update_status_color(searchrow, '#000000'); - customer.disabled = false; - customer.style.backgroundColor = '#ffffff'; - - if ( customerArray.length == 0 ) { - - customer.value = 'Not found'; - customer.style.color = '#ff0000'; - custnum_obj.style.color = '#ff0000'; - - } else if ( customerArray.length == 5 ) { - - custnum_obj.value = customerArray[0]; - custnum_obj.style.color = '#000000'; - customer.value = customerArray[1]; - balance.innerHTML = '<% $money_char %>' + customerArray[2] + '   '; - status.innerHTML = customerArray[3]; - status.style.color = '#'+customerArray[4]; + function search_custnum_update(customers) { - customer.style.display = ''; - customer_select.style.display = 'none'; + var customerArray = eval('(' + customers + ')') || []; + update_customer(searchrow, customerArray); % if ( $opt{custnum_update_callback} ) { <% $opt{custnum_update_callback} %>(searchrow, '<% $opt{prefix} %>') % } - } } custnum_search(custnum, search_custnum_update ); @@ -251,39 +236,16 @@ Example: var customer_select = document.getElementById('cust_select'+searchrow); - var balance = document.getElementById('balance'+searchrow); - balance.innerHTML = ''; - - var status = document.getElementById('status'+searchrow); - status.innerHTML = ''; - function search_customer_update(customers) { - var customerArray = eval('(' + customers + ')'); + var customerArrayArray = eval('(' + customers + ')') || [ [] ]; custnum_obj.disabled = false; custnum_obj.style.backgroundColor = '#ffffff'; - if ( customerArray.length == 0 ) { - - custnum_obj.value = 'Not found'; - custnum_obj.style.color = '#ff0000'; - customer_obj.style.color = '#ff0000'; - - customer_obj.style.display = ''; - customer_select.style.display = 'none'; - - } else if ( customerArray.length == 1 ) { - - custnum_obj.value = customerArray[0][0]; - customer_obj.value = customerArray[0][1]; - balance.innerHTML = '<% $money_char %>' + customerArray[0][2] + '   '; - status.innerHTML = customerArray[0][3]; - status.style.color = '#'+customerArray[0][4]; - - customer_obj.style.display = ''; - customer_select.style.display = 'none'; + if ( customerArrayArray.length == 1 ) { + update_customer(customerArrayArray[1]); % if ( $opt{custnum_update_callback} ) { <% $opt{custnum_update_callback} %>(searchrow, '<% $opt{prefix} %>') % } @@ -294,14 +256,16 @@ Example: custnum_obj.style.color = '#ff0000'; //blank the current list - for ( var i = customer_select.length; i >= 0; i-- ) - customer_select.options[i] = null; + customer_select.options.length = 0; opt(customer_select, '', 'Multiple customers match "' + customer + '" - select one', '#ff0000'); - //add the multiple customers - for ( var s = 0; s < customerArray.length; s++ ) - opt(customer_select, customerArray[s][0] + '_' + customerArray[s][2] + '_' + customerArray[s][3] + '_' + customerArray[s][4], customerArray[s][1], '#000000'); + for ( var s = 0; s < customerArrayArray.length; s++ ) { + opt(customer_select, + JSON.stringify(customerArrayArray[s]), + customerArrayArray[s][1], + '#000000'); + } opt(customer_select, 'cancel', '(Edit search string)', '#000000'); @@ -341,27 +305,7 @@ Example: } else { - var pos_underscore1 = custnum_balance_status.indexOf('_'); - var pos_underscore2 = custnum_balance_status.indexOf('_',pos_underscore1+1); - var pos_underscore3 = custnum_balance_status.indexOf('_',pos_underscore2+1); - var custnum = custnum_balance_status.substring(0,pos_underscore1); - var balance = custnum_balance_status.substring(pos_underscore1+1,pos_underscore2) + '   '; - var status = custnum_balance_status.substring(pos_underscore2+1,pos_underscore3); - var color = custnum_balance_status.substring(pos_underscore3+1); - - custnum_obj.value = custnum; - custnum_obj.style.color = '#000000'; - - customer_obj.value = customer; - customer_obj.style.color = '#000000'; - - balance_obj.innerHTML = '<% $money_char %>' + balance; - - status_obj.innerHTML = status; - status_obj.style.color = '#'+color; - - this.style.display = 'none'; - customer_obj.style.display = ''; + update_customer(searchrow, JSON.parse(custnum_balance_status)); % if ( $opt{custnum_update_callback} ) { <% $opt{custnum_update_callback} %>(searchrow, '<% $opt{prefix} %>') @@ -378,6 +322,23 @@ Example: what.options[length] = optionName; } + function update_status_text(rownum, newval) { + document.getElementById('status'+rownum).value = newval; + document.getElementById('status'+rownum+'_text').innerHTML = newval; + } + + function update_status_color(rownum, newval) { + document.getElementById('statuscolor'+rownum).value = newval; + document.getElementById('status'+rownum+'_text').style.color = newval; + } + + function update_balance_text(rownum, newval) { + document.getElementById('balance'+rownum).value = newval; + document.getElementById('balance'+rownum+'_text').innerHTML = newval; + } + + +
@@ -430,14 +391,26 @@ Example: - + + % my $col = 0; % foreach my $field ( @{$opt{fields}} ) { % my $value; @@ -494,15 +482,6 @@ Example: % $col++; % } - % } @@ -613,15 +592,28 @@ Example: row.appendChild(custnum_cell); var status_cell = document.createElement('TD'); + status_cell.style.textAlign = 'center'; - var status_span = document.createElement('SPAN'); - status_span.setAttribute('name', 'status'+<% $opt{prefix} %>rownum); - status_span.setAttribute('id', 'status'+<% $opt{prefix} %>rownum); - status_span.style.textAlign = 'center'; - status_span.style.fontWeight = 'bold'; - status_span.setAttribute('rownum', <% $opt{prefix} %>rownum); - status_cell.appendChild(status_span); + var status_span = document.createElement('SPAN'); + status_span.setAttribute('id', 'status'+<% $opt{prefix} %>rownum+'_text'); + status_span.style.fontWeight = 'bold'; + status_span.setAttribute('rownum', <% $opt{prefix} %>rownum); + status_cell.appendChild(status_span); + var status_input = document.createElement('INPUT'); + status_input.setAttribute('type', 'hidden'); + status_input.setAttribute('name', 'status'+<% $opt{prefix} %>rownum); + status_input.setAttribute('id', 'status'+<% $opt{prefix} %>rownum); + status_input.setAttribute('rownum', <% $opt{prefix} %>rownum); + status_cell.appendChild(status_input); + + var statuscolor_input = document.createElement('INPUT'); + statuscolor_input.setAttribute('type', 'hidden'); + statuscolor_input.setAttribute('name', 'statuscolor'+<% $opt{prefix} %>rownum); + statuscolor_input.setAttribute('id', 'statuscolor'+<% $opt{prefix} %>rownum); + statuscolor_input.setAttribute('rownum', <% $opt{prefix} %>rownum); + status_cell.appendChild(statuscolor_input); + row.appendChild(status_cell); var customer_cell = document.createElement('TD'); @@ -649,13 +641,25 @@ Example: row.appendChild(customer_cell); var balance_cell = document.createElement('TD'); - balance_cell.style.textAlign = 'right'; - - var balance_span = document.createElement('SPAN'); - balance_span.setAttribute('name', 'balance'+<% $opt{prefix} %>rownum); - balance_span.setAttribute('id', 'balance'+<% $opt{prefix} %>rownum); - balance_span.setAttribute('rownum', <% $opt{prefix} %>rownum); - balance_cell.appendChild(balance_span); + + balance_cell.style.textAlign = 'right'; + balance_cell.appendChild(document.createTextNode('<%$money_char%>')); + + var balance_span = document.createElement('SPAN'); + balance_span.setAttribute('id', 'balance'+<% $opt{prefix} %>rownum+'_text'); + balance_span.setAttribute('rownum', <% $opt{prefix} %>rownum); + balance_cell.appendChild(balance_span); + + balance_cell.appendChild( + document.createTextNode(String.fromCharCode(160)) //  + ); + + var balance_input = document.createElement('INPUT'); + balance_input.setAttribute('type', 'hidden'); + balance_input.setAttribute('name', 'balance'+<% $opt{prefix} %>rownum); + balance_input.setAttribute('id', 'balance'+<% $opt{prefix} %>rownum); + balance_input.setAttribute('rownum', <% $opt{prefix} %>rownum); + balance_cell.appendChild(balance_input); row.appendChild(balance_cell); @@ -676,9 +680,10 @@ Example: my_cell.appendChild(my_text); % } +% my $name = (ref($field) eq 'CODE') ? "column${col}_" : $field; var my_input = document.createElement('INPUT'); - my_input.setAttribute('name', '<% $field %>'+<% $opt{prefix} %>rownum); - my_input.setAttribute('id', '<% $field %>'+<% $opt{prefix} %>rownum); + my_input.setAttribute('name', '<% $name %>'+<% $opt{prefix} %>rownum); + my_input.setAttribute('id', '<% $name %>'+<% $opt{prefix} %>rownum); my_input.style.textAlign = '<% $align{ $opt{align}->[$col] || 'l' } %>'; my_input.setAttribute('size', <% $sizes->[$col] || 10 %>); % if ($types->[$col] eq 'immutable') { @@ -725,7 +730,7 @@ my $conf = new FS::Conf; $opt{prefix} = '' unless defined $opt{prefix}; $opt{prefix} .= '_' if $opt{prefix}; -my $types = $opt{'types'} ? [ @{$opt{'types'}} ] : []; +my $types = $opt{'type'} ? [ @{$opt{'type'}} ] : []; my $sizes = $opt{'size'} ? [ @{$opt{'size'}} ] : []; my $param = $opt{param}; @@ -742,5 +747,4 @@ my %align = ( ); my $money_char = $conf->config('money_char') || '$'; - diff --git a/httemplate/misc/batch-cust_pay.html b/httemplate/misc/batch-cust_pay.html index 11fdeee61..2e798652d 100644 --- a/httemplate/misc/batch-cust_pay.html +++ b/httemplate/misc/batch-cust_pay.html @@ -62,10 +62,10 @@ function select_discount_term(row, prefix) { name_singular => 'payment', header => \@header, fields => \@fields, - types => \@types, + type => \@types, align => \@align, - sizes => \@sizes, - colors => \@colors, + size => \@sizes, + color => \@colors, param => \%param, footer => \@footer, footer_align => \@footer_align, @@ -96,18 +96,19 @@ die "access denied" my $conf = new FS::Conf; my $money_char = $conf->config('money_char') || '$'; -my @header = ( '', 'Amount', 'Check #' ); -my @fields = ( sub { "$money_char" }, 'paid', 'payinfo' ); -my @types = ( 'immutable', '', '' ); -my @align = ( 'c', 'r', 'r' ); -my @sizes = ( 0, 8, 10 ); -my @colors = ( '', '', '' ); +my @header = ( 'Amount', 'Check #' ); +my @fields = ( 'paid', 'payinfo' ); +my @types = ( '', '' ); +my @align = ( 'r', 'r' ); +my @sizes = ( 8, 10 ); +my @colors = ( '', '' ); my %param = (); -my @footer = ( "$money_char", '_TOTAL', '' ); -my @footer_align = ( 'c', 'r', 'r' ); +my @footer = ( '_TOTAL', '' ); +my @footer_align = ( 'r', 'r' ); my $custnum_update_callback = ''; if ( FS::Record->scalar_sql('SELECT COUNT(*) FROM part_pkg_discount') ) { + #push @header, 'Discount'; push @header, ''; push @fields, 'discount_term'; push @types, 'immutable'; @@ -119,6 +120,7 @@ if ( FS::Record->scalar_sql('SELECT COUNT(*) FROM part_pkg_discount') ) { $custnum_update_callback = 'select_discount_term'; } +#push @header, 'Error'; push @header, ''; push @fields, 'error'; push @types, 'immutable'; diff --git a/httemplate/misc/process/batch-cust_pay.cgi b/httemplate/misc/process/batch-cust_pay.cgi index aa371266c..a6b90ea74 100644 --- a/httemplate/misc/process/batch-cust_pay.cgi +++ b/httemplate/misc/process/batch-cust_pay.cgi @@ -19,7 +19,7 @@ % 'extra_sql' => ' AND '. $FS::CurrentUser::CurrentUser->agentnums_sql, % }); % } -% if ( !$cust_main ) { # not found, try agent_custid +% if ( length($custnum) and !$cust_main ) { # not found, try agent_custid % $cust_main = qsearchs({ % 'table' => 'cust_main', % 'hashref' => { 'agent_custid' => $custnum }, diff --git a/httemplate/misc/xmlhttp-cust_main-discount_terms.cgi b/httemplate/misc/xmlhttp-cust_main-discount_terms.cgi index 71e2da597..b524e69fc 100644 --- a/httemplate/misc/xmlhttp-cust_main-discount_terms.cgi +++ b/httemplate/misc/xmlhttp-cust_main-discount_terms.cgi @@ -2,15 +2,18 @@ % % my $return = []; % my $custnum = $cgi->param('arg'); -% my $cust_main = ''; -% $cust_main = qsearchs({ -% 'table' => 'cust_main', -% 'hashref' => { 'custnum' => $custnum }, -% 'extra_sql' => ' AND '. $FS::CurrentUser::CurrentUser->agentnums_sql, -% }); +% if ( $custnum =~ /^\d+$/ ) { +% my $cust_main = ''; +% $cust_main = qsearchs({ +% 'table' => 'cust_main', +% 'hashref' => { 'custnum' => $custnum }, +% 'extra_sql' => ' AND '. $FS::CurrentUser::CurrentUser->agentnums_sql, +% }); % -% if ($cust_main) { -% $return = [ map [ $_, "$_ months" ], $cust_main->discount_terms ]; +% if ($cust_main) { +% $return = [ map [ $_, sprintf("%d months", $_) ], +% $cust_main->discount_terms ]; +% } % } % <% objToJson($return) %> diff --git a/httemplate/misc/xmlhttp-cust_main-search.cgi b/httemplate/misc/xmlhttp-cust_main-search.cgi index 68c5bf597..436501e8b 100644 --- a/httemplate/misc/xmlhttp-cust_main-search.cgi +++ b/httemplate/misc/xmlhttp-cust_main-search.cgi @@ -18,9 +18,13 @@ % } elsif ( $sub eq 'invnum_search' ) { % % my $string = $cgi->param('arg'); -% my $inv = qsearchs('cust_bill', { 'invnum' => $string }); -% my $return = $inv ? findbycustnum($inv->custnum,0) : []; +% if ( $string =~ /^(\d+)$/ ) { +% my $inv = qsearchs('cust_bill', { 'invnum' => $1 }); +% my $return = $inv ? findbycustnum($inv->custnum,0) : []; <% objToJson($return) %> +% } else { #return nothing +[] +% } % } % elsif ( $sub eq 'exact_search' ) { % # XXX possibly should query each element separately -- cgit v1.2.1
- + " + + ><% $param->{"status$row"} %> + " + rownum = "<% $row %>" + > + " rownum = "<% $row %>" - STYLE = "text-align:center; font-weight: bold" > - @@ -456,6 +429,21 @@ Example: + <% $money_char %> + <% $param->{"balance$row"} %> +   + " + rownum = "<% $row %>" + > + - - -   -