From 08662d58e7b9a13cf841e9c89daa39b28655724e Mon Sep 17 00:00:00 2001 From: ivan Date: Thu, 14 Jul 2005 10:52:46 +0000 Subject: [PATCH] move account search (httemplate/search/svc_acct.cgi) to new template, cust-fields configuration value to control which customer fields are shown on reports --- Changes.1.5.8 | 2 + FS/FS/Conf.pm | 17 ++ FS/FS/UI/Web.pm | 98 +++++++++ FS/FS/cust_bill.pm | 12 +- FS/FS/cust_bill_event.pm | 10 +- FS/FS/cust_credit.pm | 11 +- FS/FS/cust_main.pm | 44 +++- FS/FS/cust_main_Mixin.pm | 103 ++++++++++ FS/FS/cust_pay.pm | 11 +- FS/FS/svc_Common.pm | 21 +- FS/MANIFEST | 2 + FS/t/cust_main_Mixin.t | 5 + httemplate/search/cust_bill_event.cgi | 25 ++- httemplate/search/cust_credit.html | 33 +-- httemplate/search/cust_pay.cgi | 34 ++-- httemplate/search/elements/search.html | 23 ++- httemplate/search/report_receivables.cgi | 26 ++- httemplate/search/svc_acct.cgi | 336 +++++++++---------------------- httemplate/search/svc_domain.cgi | 18 +- httemplate/search/svc_forward.cgi | 15 +- httemplate/search/svc_www.cgi | 19 +- 21 files changed, 526 insertions(+), 339 deletions(-) create mode 100644 Changes.1.5.8 create mode 100644 FS/FS/cust_main_Mixin.pm create mode 100644 FS/t/cust_main_Mixin.t diff --git a/Changes.1.5.8 b/Changes.1.5.8 new file mode 100644 index 000000000..113078bb2 --- /dev/null +++ b/Changes.1.5.8 @@ -0,0 +1,2 @@ +- move account search (httemplate/search/svc_acct.cgi) to new template +- cust-fields configuration value to control which customer fields are shown on reports diff --git a/FS/FS/Conf.pm b/FS/FS/Conf.pm index d78135ad0..78b1f6179 100644 --- a/FS/FS/Conf.pm +++ b/FS/FS/Conf.pm @@ -1545,6 +1545,23 @@ httemplate/docs/config.html 'type' => 'checkbox', }, + { + 'key' => 'cust-fields', + 'section' => 'UI', + 'description' => 'Which customer fields to display on reports', + 'type' => 'select', + 'select_enum' => [ + 'Customer: Last, First or Company (Last, First)', + 'Cust# | Customer: custnum | Last, First or Company (Last, First)', + 'Name | Company: Last, First | Company', + 'Cust# | Name | Company: custnum | Last, First | Company', + '(bill) Customer | (service) Customer: Last, First or Company (Last, First) | (same for service address if present)', + 'Cust# | (bill) Customer | (service) Customer: custnum | Last, First or Company (Last, First) | (same for service address if present)', + '(bill) Name | (bill) Company | (service) Name | (service) Company: Last, First | Company | (same for service address if present)', + 'Cust# | (bill) Name | (bill) Company | (service) Name | (service) Company: custnum | Last, First | Company | (same for service address if present)', + ], + }, + ); 1; diff --git a/FS/FS/UI/Web.pm b/FS/FS/UI/Web.pm index e701141ec..716fd861f 100644 --- a/FS/FS/UI/Web.pm +++ b/FS/FS/UI/Web.pm @@ -1,5 +1,8 @@ package FS::UI::Web; +use FS::Conf; +use FS::Record qw(dbdef); + #use vars qw(@ISA); #use FS::UI #@ISA = qw( FS::UI ); @@ -18,7 +21,102 @@ sub parse_beginning_ending { ( $beginning, $ending ); } +### +# cust_main report methods +### + +=item cust_header + +Returns an array of customer information headers according to the +B configuration setting. + +=cut + +use vars qw( @cust_fields ); + +sub cust_sql_fields { + my @fields = qw( last first company ); + push @fields, map "ship_$_", @fields + if dbdef->table('cust_main')->column('ship_last'); + map "cust_main.$_", @fields; +} + +sub cust_header { + + warn "FS::svc_Common::cust_header called" + if $DEBUG; + + my $conf = new FS::Conf; + + my %header2method = ( + 'Customer' => 'name', + 'Cust#' => 'custnum', + 'Name' => 'contact', + 'Company' => 'company', + '(bill) Customer' => 'name', + '(service) Customer' => 'ship_name', + '(bill) Name' => 'contact', + '(service) Name' => 'ship_contact', + '(bill) Company' => 'company', + '(service) Company' => 'ship_company', + ); + + my @cust_header; + if ( $conf->exists('cust-fields') + && $conf->config('cust-fields') =~ /^([\w \|\#\(\)]+):/ + ) + { + warn " found cust-fields configuration value" + if $DEBUG; + + my $cust_fields = $1; + @cust_header = split(/ \| /, $cust_fields); + @cust_fields = map { $header2method{$_} } @cust_header; + } else { + warn " no cust-fields configuration value found; using default 'Customer'" + if $DEBUG; + @cust_header = ( 'Customer' ); + @cust_fields = ( 'cust_name' ); + } + + #my $svc_x = shift; + @cust_header; +} + +=item cust_fields + +Given a svc_ object that contains fields from cust_main (say, from a +JOINed search. See httemplate/search/svc_* for examples), returns an array +of customer information according to the cust-fields configuration +setting, or "(unlinked)" if this service is not linked to a customer. + +=cut + +sub cust_fields { + my $svc_x = shift; + warn "FS::svc_Common::cust_fields called for $svc_x ". + "(cust_fields: @cust_fields)" + if $DEBUG > 1; + + cust_header() unless @cust_fields; + + my $seen_unlinked = 0; + map { + if ( $svc_x->custnum ) { + warn " $svc_x -> $_" + if $DEBUG > 1; + $svc_x->$_(@_); + } else { + warn " ($svc_x unlinked)" + if $DEBUG > 1; + $seen_unlinked++ ? '' : '(unlinked)'; + } + } @cust_fields; +} + +### # begin JSRPC code... +### package FS::UI::Web::JSRPC; diff --git a/FS/FS/cust_bill.pm b/FS/FS/cust_bill.pm index b9a99c900..d9e04de53 100644 --- a/FS/FS/cust_bill.pm +++ b/FS/FS/cust_bill.pm @@ -11,8 +11,9 @@ use String::ShellQuote; use HTML::Entities; use Locale::Country; use FS::UID qw( datasrc ); -use FS::Record qw( qsearch qsearchs ); use FS::Misc qw( send_email send_fax ); +use FS::Record qw( qsearch qsearchs ); +use FS::cust_main_Mixin; use FS::cust_main; use FS::cust_bill_pkg; use FS::cust_credit; @@ -25,7 +26,7 @@ use FS::part_pkg; use FS::cust_bill_pay; use FS::part_bill_event; -@ISA = qw( FS::Record ); +@ISA = qw( FS::cust_main_Mixin FS::Record ); $DEBUG = 0; @@ -105,6 +106,13 @@ Invoices are normally created by calling the bill method of a customer object sub table { 'cust_bill'; } +sub cust_linked { $_[0]->cust_main_custnum; } +sub cust_unlinked_msg { + my $self = shift; + "WARNING: can't find cust_main.custnum ". $self->custnum. + ' (cust_bill.invnum '. $self->invnum. ')'; +} + =item insert Adds this invoice to the database ("Posts" the invoice). If there is an error, diff --git a/FS/FS/cust_bill_event.pm b/FS/FS/cust_bill_event.pm index 7b981391e..128e5a53d 100644 --- a/FS/FS/cust_bill_event.pm +++ b/FS/FS/cust_bill_event.pm @@ -3,10 +3,11 @@ package FS::cust_bill_event; use strict; use vars qw( @ISA $DEBUG ); use FS::Record qw( qsearch qsearchs ); +use FS::cust_main_Mixin; use FS::cust_bill; use FS::part_bill_event; -@ISA = qw(FS::Record); +@ISA = qw(FS::cust_main_Mixin FS::Record); $DEBUG = 0; @@ -70,6 +71,13 @@ points to. You can ask the object for a copy with the I method. sub table { 'cust_bill_event'; } +sub cust_linked { $_[0]->cust_main_custnum; } +sub cust_unlinked_msg { + my $self = shift; + "WARNING: can't find cust_main.custnum ". $self->custnum. + ' (cust_bill.invnum '. $self->invnum. ')'; +} + =item insert Adds this record to the database. If there is an error, returns the error, diff --git a/FS/FS/cust_credit.pm b/FS/FS/cust_credit.pm index 026b92e84..9cc92d2e8 100644 --- a/FS/FS/cust_credit.pm +++ b/FS/FS/cust_credit.pm @@ -4,13 +4,14 @@ use strict; use vars qw( @ISA $conf $unsuspendauto ); use Date::Format; use FS::UID qw( dbh getotaker ); -use FS::Record qw( qsearch qsearchs ); use FS::Misc qw(send_email); +use FS::Record qw( qsearch qsearchs ); +use FS::cust_main_Mixin; use FS::cust_main; use FS::cust_refund; use FS::cust_credit_bill; -@ISA = qw( FS::Record ); +@ISA = qw( FS::cust_main_Mixin FS::Record ); #ask FS::UID to run this stuff for us later $FS::UID::callback{'FS::cust_credit'} = sub { @@ -75,6 +76,12 @@ Creates a new credit. To add the credit to the database, see L<"insert">. =cut sub table { 'cust_credit'; } +sub cust_linked { $_[0]->cust_main_custnum; } +sub cust_unlinked_msg { + my $self = shift; + "WARNING: can't find cust_main.custnum ". $self->custnum. + ' (cust_credit.crednum '. $self->crednum. ')'; +} =item insert diff --git a/FS/FS/cust_main.pm b/FS/FS/cust_main.pm index 1bbf191ec..ab2c74a50 100644 --- a/FS/FS/cust_main.pm +++ b/FS/FS/cust_main.pm @@ -3160,11 +3160,53 @@ Returns a name string for this customer, either "Company (Last, First)" or sub name { my $self = shift; - my $name = $self->get('last'). ', '. $self->first; + my $name = $self->bill_contact; $name = $self->company. " ($name)" if $self->company; $name; } +=item ship_name + +Returns a name string for this (service/shipping) contact, either +"Company (Last, First)" or "Last, First". + +=cut + +sub ship_name { + my $self = shift; + if ( $self->get('ship_last') ) { + my $name = $self->ship_contact; + $name = $self->ship_company. " ($name)" if $self->ship_company; + $name; + } else { + $self->name; + } +} + +=item contact + +Returns this customer's full (billing) contact name only, "Last, First" + +=cut + +sub contact { + my $self = shift; + $self->get('last'). ', '. $self->first; +} + +=item ship_contact + +Returns this customer's full (shipping) contact name only, "Last, First" + +=cut + +sub ship_contact { + my $self = shift; + $self->get('ship_last') + ? $self->get('ship_last'). ', '. $self->ship_first + : $self->bill_contact; +} + =item status Returns a status string for this customer, currently: diff --git a/FS/FS/cust_main_Mixin.pm b/FS/FS/cust_main_Mixin.pm new file mode 100644 index 000000000..a114c5a8a --- /dev/null +++ b/FS/FS/cust_main_Mixin.pm @@ -0,0 +1,103 @@ +package FS::cust_main_Mixin; + +use strict; +use FS::cust_main; + +=head1 NAME + +FS::cust_main_Mixin - Mixin class for records that contain fields from cust_main + +=head1 SYNOPSIS + +package FS::some_table; +use vars qw(@ISA); +@ISA = qw( FS::cust_main_Mixin FS::Record ); + +=head1 DESCRIPTION + +This is a mixin class for records that contain fields from the cust_main table, +for example, from a JOINed search. See httemplate/search/ for examples. + +=head1 METHODS + +=over 4 + +=item name + +Given an object that contains fields from cust_main (say, from a JOINed +search; see httemplate/search/ for examples), returns the equivalent of the +FS::cust_main I method, or "(unlinked)" if this object is not linked to +a customer. + +=cut + +sub cust_unlinked_msg { '(unlinked)'; } +sub cust_linked { $_[0]->custnum; } + +sub name { + my $self = shift; + $self->cust_linked + ? FS::cust_main::name($self) + : $self->cust_unlinked_msg; +} + +=item ship_name + +Given an object that contains fields from cust_main (say, from a JOINed +search; see httemplate/search/ for examples), returns the equivalent of the +FS::cust_main I method, or "(unlinked)" if this object is not +linked to a customer. + +=cut + +sub ship_name { + my $self = shift; + $self->cust_linked + ? FS::cust_main::ship_name($self) + : $self->cust_unlinked_msg; +} + +=item contact + +Given an object that contains fields from cust_main (say, from a JOINed +search; see httemplate/search/ for examples), returns the equivalent of the +FS::cust_main I method, or "(unlinked)" if this object is not linked +to a customer. + +=cut + +sub contact { + my $self = shift; + $self->cust_linked + ? FS::cust_main::contact($self) + : $self->cust_unlinked_msg; +} + +=item ship_contact + +Given an object that contains fields from cust_main (say, from a JOINed +search; see httemplate/search/ for examples), returns the equivalent of the +FS::cust_main I method, or "(unlinked)" if this object is not +linked to a customer. + +=cut + +sub ship_contact { + my $self = shift; + $self->cust_linked + ? FS::cust_main::ship_contact($self) + : $self->cust_unlinked_msg; +} + +=back + +=head1 BUGS + +=head1 SEE ALSO + +L, L + +=cut + +1; + diff --git a/FS/FS/cust_pay.pm b/FS/FS/cust_pay.pm index ccf991dc1..0f872a4d2 100644 --- a/FS/FS/cust_pay.pm +++ b/FS/FS/cust_pay.pm @@ -5,15 +5,16 @@ use vars qw( @ISA $conf $unsuspendauto $ignore_noapply ); use Date::Format; use Business::CreditCard; use Text::Template; -use FS::Record qw( dbh qsearch qsearchs ); use FS::Misc qw(send_email); +use FS::Record qw( dbh qsearch qsearchs ); +use FS::cust_main_Mixin; use FS::cust_bill; use FS::cust_bill_pay; use FS::cust_pay_refund; use FS::cust_main; use FS::cust_pay_void; -@ISA = qw( FS::Record ); +@ISA = qw( FS::cust_main_Mixin FS::Record ); $ignore_noapply = 0; @@ -81,6 +82,12 @@ Creates a new payment. To add the payment to the databse, see L<"insert">. =cut sub table { 'cust_pay'; } +sub cust_linked { $_[0]->cust_main_custnum; } +sub cust_unlinked_msg { + my $self = shift; + "WARNING: can't find cust_main.custnum ". $self->custnum. + ' (cust_pay.paynum '. $self->paynum. ')'; +} =item insert diff --git a/FS/FS/svc_Common.pm b/FS/FS/svc_Common.pm index 80d5e21a6..205c33078 100644 --- a/FS/FS/svc_Common.pm +++ b/FS/FS/svc_Common.pm @@ -3,15 +3,16 @@ package FS::svc_Common; use strict; use vars qw( @ISA $noexport_hack $DEBUG ); use FS::Record qw( qsearch qsearchs fields dbh ); +use FS::cust_main_Mixin; use FS::cust_svc; use FS::part_svc; use FS::queue; use FS::cust_main; -@ISA = qw( FS::Record ); +@ISA = qw( FS::cust_main_Mixin FS::Record ); -$DEBUG = 0; -#$DEBUG = 1; +#$DEBUG = 0; +$DEBUG = 1; =head1 NAME @@ -547,20 +548,6 @@ sub clone_kludge_unsuspend { shift; } -=item cust_name - -Given a svc_ object that contains fields from cust_main (say, from a -JOINed search. See httemplate/search/svc_* for examples), returns the -equivalent of "$svc_x->cust_svc->cust_pkg->name" (but much more efficient), -or "(unlinked)" if this service is not linked to a customer. - -=cut - -sub cust_name { - my $svc_x = shift; - $svc_x->custnum ? FS::cust_main::name($svc_x) : '(unlinked)'; -} - =back =head1 BUGS diff --git a/FS/MANIFEST b/FS/MANIFEST index 971fe403e..fa2cef097 100644 --- a/FS/MANIFEST +++ b/FS/MANIFEST @@ -52,6 +52,7 @@ FS/cust_bill_pkg_detail.pm FS/cust_credit.pm FS/cust_credit_bill.pm FS/cust_main.pm +FS/cust_main_Mixin.pm FS/cust_main_county.pm FS/cust_main_invoice.pm FS/cust_pay.pm @@ -177,6 +178,7 @@ t/cust_credit.t t/cust_credit_bill.t t/cust_credit_refund.t t/cust_main.t +t/cust_main_Mixin.t t/cust_main_county.t t/cust_main_invoice.t t/cust_pay.t diff --git a/FS/t/cust_main_Mixin.t b/FS/t/cust_main_Mixin.t new file mode 100644 index 000000000..c8b929117 --- /dev/null +++ b/FS/t/cust_main_Mixin.t @@ -0,0 +1,5 @@ +BEGIN { $| = 1; print "1..1\n" } +END {print "not ok 1\n" unless $loaded;} +use FS::cust_main_Mixin; +$loaded=1; +print "ok 1\n"; diff --git a/httemplate/search/cust_bill_event.cgi b/httemplate/search/cust_bill_event.cgi index f34bb68f4..df4dcbf42 100644 --- a/httemplate/search/cust_bill_event.cgi +++ b/httemplate/search/cust_bill_event.cgi @@ -27,8 +27,8 @@ my $sql_query = { 'part_bill_event.event', 'cust_bill.custnum', 'cust_bill._date AS cust_bill_date', - map "cust_main.$_", qw(last first company) - + 'cust_main.custnum AS cust_main_custnum', + FS::UI::Web::cust_sql_fields(), ), 'extra_sql' => "$where ORDER BY _date ASC", 'addl_from' => 'LEFT JOIN part_bill_event USING ( eventpart ) '. @@ -71,6 +71,13 @@ push @$menubar, 'Re-fax these events' => "javascript:fax_process()" if $conf->exists('hylafax'); +my $link_cust = sub { + my $cust_bill_event = shift; + $cust_bill_event->cust_main_custnum + ? [ "${p}view/cust_main.cgi?", 'custnum' ] + : ''; +}; + %><%= include( 'elements/search.html', 'title' => $title, 'html_init' => $html_init, @@ -78,9 +85,12 @@ push @$menubar, 'Re-fax these events' => 'name' => 'billing events', 'query' => $sql_query, 'count_query' => $count_sql, - 'header' => [ qw( Event Date Status ), + 'header' => [ 'Event', + 'Date', + 'Status', #'Inv #', 'Inv Date', 'Cust #', - 'Invoice', 'Cust #', + 'Invoice', + FS::UI::Web::cust_header(), ], 'fields' => [ 'event', @@ -99,9 +109,7 @@ push @$menubar, 'Re-fax these events' => time2str("%D", $_[0]->cust_bill_date). ')'; }, - sub { FS::cust_main::name($_[0]) }, - - + \&FS::UI::Web::cust_fields, ], 'links' => [ '', @@ -113,8 +121,7 @@ push @$menubar, 'Re-fax these events' => $template .= '-' if $template; [ "${p}view/cust_bill.cgi?$template", 'invnum']; }, - [ "${p}view/cust_main.cgi?", 'custnum' ], - [ "${p}view/cust_main.cgi?", 'custnum' ], + ( map { $link_cust } FS::UI::Web::cust_header() ), ], ) %> diff --git a/httemplate/search/cust_credit.html b/httemplate/search/cust_credit.html index b978e6238..4b3da605a 100755 --- a/httemplate/search/cust_credit.html +++ b/httemplate/search/cust_credit.html @@ -46,13 +46,22 @@ my $sql_query = { 'table' => 'cust_credit', - 'select' => 'cust_credit.*, cust_main.last, cust_main.first, cust_main.company', + 'select' => join(', ', + 'cust_credit.*', + 'cust_main.custnum as cust_main_custnum', + FS::UI::Web::cust_sql_fields(), + ), 'hashref' => {}, 'extra_sql' => $where, 'addl_from' => 'LEFT JOIN cust_main USING ( custnum )', }; - my $clink = [ "${p}view/cust_main.cgi?", 'custnum' ]; + my $clink = sub { + my $cust_bill = shift; + $cust_bill->cust_main_custnum + ? [ "${p}view/cust_main.cgi?", 'custnum' ] + : ''; + }; %><%= include( 'elements/search.html', 'title' => $title, @@ -61,26 +70,26 @@ 'count_query' => $count_query, 'count_addl' => [ '$%.2f total credited', ], #'redirect' => $link, - 'header' => - [ qw(Amount Date), 'Cust #', 'Contact name', - qw(Company By Reason) ], + 'header' => [ 'Amount', + 'Date', + FS::UI::Web::cust_header(), + 'By', + 'Reason' + ], 'fields' => [ #'crednum', sub { sprintf('$%.2f', shift->amount ) }, sub { time2str('%b %d %Y', shift->_date ) }, - 'custnum', - sub { $_[0]->get('last'). ', '. $_[0]->first; }, - 'company', + \&FS::UI::Web::cust_fields, 'otaker', 'reason', ], - 'align' => 'rrrllll', + #'align' => 'rrrllll', + 'align' => 'rr', 'links' => [ '', '', - $clink, - $clink, - $clink, + ( map { $clink } FS::UI::Web::cust_header() ), '', '', ], diff --git a/httemplate/search/cust_pay.cgi b/httemplate/search/cust_pay.cgi index c23653aa9..a680479f3 100755 --- a/httemplate/search/cust_pay.cgi +++ b/httemplate/search/cust_pay.cgi @@ -73,7 +73,11 @@ $sql_query = { 'table' => 'cust_pay', - 'select' => 'cust_pay.*, cust_main.last, cust_main.first, cust_main.company', + 'select' => join(', ', + 'cust_pay.*', + 'cust_main.custnum as cust_main_custnum', + FS::UI::Web::cust_sql_fields(), + ), 'hashref' => {}, 'extra_sql' => "$search ORDER BY _date", 'addl_from' => 'LEFT JOIN cust_main USING ( custnum )', @@ -99,7 +103,12 @@ } - my $link = [ "${p}view/cust_main.cgi?", 'custnum' ]; + my $link = sub { + my $cust_pay = shift; + $cust_pay->cust_main_custnum + ? [ "${p}view/cust_main.cgi?", 'custnum' ] + : ''; + }; %><%= include( 'elements/search.html', 'title' => $title, @@ -107,9 +116,11 @@ 'query' => $sql_query, 'count_query' => $count_query, 'count_addl' => [ '$%.2f total paid', ], - 'header' => - [ qw(Payment Amount Date), 'Cust #', 'Contact name', - 'Company', ], + 'header' => [ 'Payment', + 'Amount', + 'Date', + FS::UI::Web::cust_header(), + ], 'fields' => [ sub { my $cust_pay = shift; @@ -119,24 +130,23 @@ 'E-check acct#'. $cust_pay->payinfo; } elsif ( $cust_pay->payby eq 'BILL' ) { 'Check #'. $cust_pay->payinfo; + } elsif ( $cust_pay->payby eq 'PREP' ) { + 'Prepaid card #'. $cust_pay->payinfo; } else { $cust_pay->payby. ' '. $cust_pay->payinfo; } }, sub { sprintf('$%.2f', shift->paid ) }, sub { time2str('%b %d %Y', shift->_date ) }, - 'custnum', - sub { $_[0]->get('last'). ', '. $_[0]->first; }, - 'company', + \&FS::UI::Web::cust_fields, ], - 'align' => 'lrrrll', + #'align' => 'lrrrll', + 'align' => 'rrr', 'links' => [ '', '', '', - $link, - $link, - $link, + ( map { $link } FS::UI::Web::cust_header() ), ], ) %> diff --git a/httemplate/search/elements/search.html b/httemplate/search/elements/search.html index 47d619444..78754fe00 100644 --- a/httemplate/search/elements/search.html +++ b/httemplate/search/elements/search.html @@ -152,7 +152,9 @@ # } #} if ( ref($field) eq 'CODE' ) { - $worksheet->write($r, $c++, &{$field}($row) ); + foreach my $value ( &{$field}($row) ) { + $worksheet->write($r, $c++, $value ); + } } else { $worksheet->write($r, $c++, $row->$field() ); } @@ -253,7 +255,18 @@ my $sizes = $opt{'size'} ? [ @{$opt{'size'}} ] : []; my $styles = $opt{'style'} ? [ @{$opt{'style'}} ] : []; - foreach my $field ( @{$opt{'fields'}} ) { + foreach my $field ( + + map { + if ( ref($_) eq 'CODE' ) { + &{$_}($row); + } else { + $row->$_(); + } + } + @{$opt{'fields'}} + + ) { my $align = $aligns ? shift @$aligns : ''; $align = " ALIGN=$align" if $align; @@ -294,11 +307,7 @@ } %> - <% if ( ref($field) eq 'CODE' ) { %> - ><%= $font %><%= $a %><%= $s %><%= &{$field}($row) %><%= $es %><%= $a ? '' : '' %><%= $font ? '' : '' %> - <% } else { %> - ><%= $font %><%= $a %><%= $s %><%= $row->$field() %><%= $es %><%= $a ? '' : '' %><%= $font ? '' : '' %> - <% } %> + ><%= $font %><%= $a %><%= $s %><%= $field %><%= $es %><%= $a ? '' : '' %><%= $font ? '' : '' %> <% } %> <% } else { %> <% foreach ( @$row ) { %> diff --git a/httemplate/search/report_receivables.cgi b/httemplate/search/report_receivables.cgi index 82ce5d777..535afcca0 100755 --- a/httemplate/search/report_receivables.cgi +++ b/httemplate/search/report_receivables.cgi @@ -118,14 +118,16 @@ END my $conf = new FS::Conf; my $money_char = $conf->config('money_char') || '$'; + my $align = join('', map { /#/ ? 'r' : 'l' } FS::UI::Web::cust_header() ). + 'crrrrr'; + %><%= include( 'elements/search.html', 'title' => 'Accounts Receivable Aging Summary', 'name' => 'customers', 'query' => $sql_query, 'count_query' => $count_sql, 'header' => [ - '#', - 'Customer', + FS::UI::Web::cust_header(), 'Status', # (me)', #'Status', # (cust_main)', '0-30', @@ -135,8 +137,12 @@ END 'Total', ], 'footer' => [ - '', 'Total', + ( map '', + ( 1 .. + scalar(FS::UI::Web::cust_header()-1) + ) + ), '', #'', sprintf( $money_char.'%.2f', @@ -151,8 +157,7 @@ END $row->{'owed_total'} ), ], 'fields' => [ - 'custnum', - 'name', + \&FS::UI::Web::cust_fields, sub { my $row = shift; my $status = 'Cancelled'; @@ -191,14 +196,15 @@ END '', ], #'align' => 'rlccrrrrr', - 'align' => 'rlcrrrrr', + 'align' => $align, #'size' => [ '', '', '-1', '-1', '', '', '', '', '', ], #'style' => [ '', '', 'b', 'b', '', '', '', '', 'b', ], - 'size' => [ '', '', '-1', '', '', '', '', '', ], - 'style' => [ '', '', 'b', '', '', '', '', 'b', ], + 'size' => [ ( map '', FS::UI::Web::cust_header() ), + '-1', '', '', '', '', '', ], + 'style' => [ ( map '', FS::UI::Web::cust_header() ), + 'b', '', '', '', '', 'b', ], 'color' => [ - '', - '', + ( map '', FS::UI::Web::cust_header() ), sub { my $row = shift; my $status = 'Cancelled'; diff --git a/httemplate/search/svc_acct.cgi b/httemplate/search/svc_acct.cgi index 1e4a03d84..d4565aefc 100755 --- a/httemplate/search/svc_acct.cgi +++ b/httemplate/search/svc_acct.cgi @@ -1,250 +1,37 @@ <% -my $conf = new FS::Conf; -my $maxrecords = $conf->config('maxsearchrecordsperpage'); - -my $orderby = ''; #removeme - -my $limit = ''; -$limit .= "LIMIT $maxrecords" if $maxrecords; - -my $offset = $cgi->param('offset') || 0; -$limit .= " OFFSET $offset" if $offset; - -my $total; +my $orderby = 'ORDER BY svcnum'; my($query)=$cgi->keywords; $query ||= ''; #to avoid use of unitialized value errors -my $unlinked = ''; +my $cjoin = ''; +my @extra_sql = (); if ( $query =~ /^UN_(.*)$/ ) { $query = $1; - my $empty = driver_name eq 'Pg' ? qq('') : qq(""); - if ( driver_name eq 'mysql' ) { - $unlinked = "LEFT JOIN cust_svc ON cust_svc.svcnum = svc_acct.svcnum - WHERE cust_svc.pkgnum IS NULL - OR cust_svc.pkgnum = 0 - OR cust_svc.pkgnum = $empty"; - } else { - $unlinked = " - WHERE 0 < - ( SELECT count(*) FROM cust_svc - WHERE cust_svc.svcnum = svc_acct.svcnum - AND ( pkgnum IS NULL OR pkgnum = 0 ) - ) - "; - } + $cjoin = 'LEFT JOIN cust_svc USING ( svcnum )'; + push @extra_sql, 'pkgnum IS NULL'; } -my $tblname = driver_name eq 'mysql' ? 'svc_acct.' : ''; -my(@svc_acct, $sortby); if ( $query eq 'svcnum' ) { - $sortby=\*svcnum_sort; - $orderby = "ORDER BY ${tblname}svcnum"; + #$orderby = "ORDER BY svcnum"; } elsif ( $query eq 'username' ) { - $sortby=\*username_sort; - $orderby = "ORDER BY ${tblname}username"; + $orderby = "ORDER BY LOWER(username)"; } elsif ( $query eq 'uid' ) { - $sortby=\*uid_sort; - $orderby = ( $unlinked ? ' AND' : ' WHERE' ). - " ${tblname}uid IS NOT NULL ORDER BY ${tblname}uid"; + $orderby = "ORDER BY uid"; + push @extra_sql, "uid IS NOT NULL"; } elsif ( $cgi->param('popnum') =~ /^(\d+)$/ ) { - $unlinked .= ( $unlinked ? 'AND' : 'WHERE' ). - " popnum = $1"; - $sortby=\*username_sort; - $orderby = "ORDER BY ${tblname}username"; + push @extra_sql, "popnum = $1"; + $orderby = "ORDER BY LOWER(username)"; } elsif ( $cgi->param('svcpart') =~ /^(\d+)$/ ) { - $unlinked .= ( $unlinked ? ' AND' : ' WHERE' ). - " $1 = ( SELECT svcpart FROM cust_svc ". - " WHERE cust_svc.svcnum = svc_acct.svcnum ) "; - $sortby=\*uid_sort; - #$sortby=\*svcnum_sort; + $cjoin ||= 'LEFT JOIN cust_svc USING ( svcnum )'; + push @extra_sql, "svcpart = $1"; + $orderby = "ORDER BY uid"; + #$orderby = "ORDER BY svcnum"; } else { - $sortby=\*uid_sort; - @svc_acct = @{&usernamesearch}; -} - - -if ( $query eq 'svcnum' - || $query eq 'username' - || $query eq 'uid' - || $cgi->param('popnum') =~ /^(\d+)$/ - || $cgi->param('svcpart') =~ /^(\d+)$/ - ) { - - my $statement = "SELECT COUNT(*) FROM svc_acct $unlinked"; - my $sth = dbh->prepare($statement) - or die dbh->errstr. " doing $statement"; - $sth->execute or die "Error executing \"$statement\": ". $sth->errstr; - - $total = $sth->fetchrow_arrayref->[0]; - - @svc_acct = qsearch('svc_acct', {}, '', "$unlinked $orderby $limit"); - -} - -if ( scalar(@svc_acct) == 1 ) { - my($svcnum)=$svc_acct[0]->svcnum; - print $cgi->redirect(popurl(2). "view/svc_acct.cgi?$svcnum"); #redirect - #exit; -} elsif ( scalar(@svc_acct) == 0 ) { #error -%> - -<% - idiot("Account not found"); -} else { -%> - -<% - $total ||= scalar(@svc_acct); - - #begin pager - my $pager = ''; - if ( $total != scalar(@svc_acct) && $maxrecords ) { - unless ( $offset == 0 ) { - $cgi->param('offset', $offset - $maxrecords); - $pager .= 'Previous '; - } - my $poff; - my $page; - for ( $poff = 0; $poff < $total; $poff += $maxrecords ) { - $page++; - if ( $offset == $poff ) { - $pager .= qq!$page !; - } else { - $cgi->param('offset', $poff); - $pager .= qq!$page !; - } - } - unless ( $offset + $maxrecords > $total ) { - $cgi->param('offset', $offset + $maxrecords); - $pager .= 'Next '; - } - } - #end pager - - print header("Account Search Results",menubar('Main Menu'=>popurl(2))), - "$total matching accounts found

$pager", - &table(), < - # - Username - Domain - UID - Service - Cust# - (bill) name - company -END - if ( defined dbdef->table('cust_main')->column('ship_last') ) { - print <(service) name - company -END - } - print ""; + $orderby = "ORDER BY uid"; - my(%saw,$svc_acct); - my $p = popurl(2); - foreach $svc_acct ( - sort $sortby grep(!$saw{$_->svcnum}++, @svc_acct) - ) { - my $cust_svc = qsearchs('cust_svc', { 'svcnum' => $svc_acct->svcnum }) - or die "No cust_svc record for svcnum ". $svc_acct->svcnum; - my $part_svc = qsearchs('part_svc', { 'svcpart' => $cust_svc->svcpart }) - or die "No part_svc record for svcpart ". $cust_svc->svcpart; - - my $domain; - my $svc_domain = qsearchs('svc_domain', { 'svcnum' => $svc_acct->domsvc }); - if ( $svc_domain ) { - $domain = "svcnum. - "\">". $svc_domain->domain. ""; - } else { - die "No svc_domain.svcnum record for svc_acct.domsvc: ". - $svc_acct->domsvc; - } - my($cust_pkg,$cust_main); - if ( $cust_svc->pkgnum ) { - $cust_pkg = qsearchs('cust_pkg', { 'pkgnum' => $cust_svc->pkgnum }) - or die "No cust_pkg record for pkgnum ". $cust_svc->pkgnum; - $cust_main = qsearchs('cust_main', { 'custnum' => $cust_pkg->custnum }) - or die "No cust_main record for custnum ". $cust_pkg->custnum; - } - my($svcnum, $username, $uid, $svc, $custnum, $last, $first, $company) = ( - $svc_acct->svcnum, - $svc_acct->getfield('username'), - $svc_acct->getfield('uid'), - $part_svc->svc, - $cust_svc->pkgnum ? $cust_main->custnum : '', - $cust_svc->pkgnum ? $cust_main->getfield('last') : '', - $cust_svc->pkgnum ? $cust_main->getfield('first') : '', - $cust_svc->pkgnum ? $cust_main->company : '', - ); - my($pcustnum) = $custnum - ? "$custnum" - : "(unlinked)" - ; - my $pname = $custnum ? "$last, $first" : ''; - my $pcompany = $custnum ? "$company" : ''; - my($pship_name, $pship_company); - if ( defined dbdef->table('cust_main')->column('ship_last') ) { - my($ship_last, $ship_first, $ship_company) = ( - $cust_svc->pkgnum ? ( $cust_main->ship_last || $last ) : '', - $cust_svc->pkgnum ? ( $cust_main->ship_last - ? $cust_main->ship_first - : $first - ) : '', - $cust_svc->pkgnum ? ( $cust_main->ship_last - ? $cust_main->ship_company - : $company - ) : '', - ); - $pship_name = $custnum ? "$ship_last, $ship_first" : ''; - $pship_company = $custnum ? "$ship_company" : ''; - } - print < - $svcnum - $username - $domain - $uid - $svc - $pcustnum - $pname - $pcompany -END - if ( defined dbdef->table('cust_main')->column('ship_last') ) { - print <$pship_name - $pship_company -END - } - print ""; - - } - - print "$pager
". - ''; - -} - -sub svcnum_sort { - $a->getfield('svcnum') <=> $b->getfield('svcnum'); -} - -sub username_sort { - $a->getfield('username') cmp $b->getfield('username'); -} - -sub uid_sort { - $a->getfield('uid') <=> $b->getfield('uid'); -} - -sub usernamesearch { - - my @svc_acct; + my @username_sql; my %username_type; foreach ( $cgi->param('username_type') ) { @@ -254,17 +41,13 @@ sub usernamesearch { $cgi->param('username') =~ /^([\w\-\.\&]+)$/; #untaint username_text my $username = $1; - if ( $username_type{'Exact'} || $username_type{'Fuzzy'} ) { - push @svc_acct, qsearch( 'svc_acct', - { 'username' => { 'op' => 'ILIKE', - 'value' => $username } } ); - } + push @username_sql, "username ILIKE '$username'" + if $username_type{'Exact'} + || $username_type{'Fuzzy'}; - if ( $username_type{'Substring'} || $username_type{'All'} ) { - push @svc_acct, qsearch( 'svc_acct', - { 'username' => { 'op' => 'ILIKE', - 'value' => "%$username%" } } ); - } + push @username_sql, "username ILIKE '\%$username\%'" + if $username_type{'Substring'} + || $username_type{'All'}; if ( $username_type{'Fuzzy'} || $username_type{'All'} ) { &FS::svc_acct::check_and_rebuild_fuzzyfiles; @@ -280,15 +63,78 @@ sub usernamesearch { #if ($username_type{'Sound-alike'}) { #} - foreach ( keys %username ) { - push @svc_acct, qsearch('svc_acct',{'username'=>$_}); - } + push @username_sql, "username = '$_'" + foreach (keys %username); } - #[ qsearch('svc_acct',{'username'=>$username}) ]; - \@svc_acct; + push @extra_sql, '( '. join( ' OR ', @username_sql). ' )'; } +my $extra_sql = + scalar(@extra_sql) + ? ' WHERE '. join(' AND ', @extra_sql ) + : ''; + +my $count_query = "SELECT COUNT(*) FROM svc_acct $cjoin $extra_sql"; +#if ( keys %svc_acct ) { +# $count_query .= ' WHERE '. +# join(' AND ', map "$_ = ". dbh->quote($svc_acct{$_}), +# keys %svc_acct +# ); +#} + +my $sql_query = { + 'table' => 'svc_acct', + 'hashref' => {}, # \%svc_acct, + 'select' => join(', ', + 'svc_acct.*', + 'cust_main.custnum', + FS::UI::Web::cust_sql_fields(), + ), + 'extra_sql' => "$extra_sql $orderby", + 'addl_from' => 'LEFT JOIN cust_svc USING ( svcnum ) '. + 'LEFT JOIN part_svc USING ( svcpart ) '. + 'LEFT JOIN cust_pkg USING ( pkgnum ) '. + 'LEFT JOIN cust_main USING ( custnum ) ', +}; + +my $link = [ "${p}view/svc_acct.cgi?", 'svcnum' ]; +my $link_cust = sub { + my $svc_acct = shift; + if ( $svc_acct->custnum ) { + [ "${p}view/cust_main.cgi?", 'custnum' ]; + } else { + ''; + } +}; + +%><%= include( 'elements/search.html', + 'title' => 'Account Search Results', + 'name' => 'accounts', + 'query' => $sql_query, + 'count_query' => $count_query, + 'redirect' => $link, + 'header' => [ '#', + 'Account', + 'UID', + 'Service', + FS::UI::Web::cust_header(), + ], + 'fields' => [ 'svcnum', + 'email', + 'uid', + 'svc', + \&FS::UI::Web::cust_fields, + ], + 'links' => [ $link, + $link, + $link, + '', + ( map { $link_cust } + FS::UI::Web::cust_header() + ), + ], + ) %> diff --git a/httemplate/search/svc_domain.cgi b/httemplate/search/svc_domain.cgi index 06041e03b..f261ea9f3 100755 --- a/httemplate/search/svc_domain.cgi +++ b/httemplate/search/svc_domain.cgi @@ -37,7 +37,6 @@ if ( keys %svc_domain ) { join(' AND ', map "$_ = ". dbh->quote($svc_domain{$_}), keys %svc_domain ); - } my $sql_query = { @@ -45,12 +44,13 @@ my $sql_query = { 'hashref' => \%svc_domain, 'select' => join(', ', 'svc_domain.*', - map "cust_main.$_", qw(custnum last first company) + 'cust_main.custnum', + FS::UI::Web::cust_sql_fields(), ), 'extra_sql' => "$extra_sql $orderby", - 'addl_from' => 'LEFT JOIN cust_svc USING ( svcnum )'. - 'LEFT JOIN cust_pkg USING ( pkgnum )'. - 'LEFT JOIN cust_main USING ( custnum )', + 'addl_from' => 'LEFT JOIN cust_svc USING ( svcnum ) '. + 'LEFT JOIN cust_pkg USING ( pkgnum ) '. + 'LEFT JOIN cust_main USING ( custnum ) ', }; my $link = [ "${p}view/svc_domain.cgi?", 'svcnum' ]; @@ -69,15 +69,17 @@ my $link_cust = sub { 'redirect' => $link, 'header' => [ '#', 'Domain', - 'Customer', + FS::UI::Web::cust_header(), ], 'fields' => [ 'svcnum', 'domain', - \&FS::svc_Common::cust_name, + \&FS::UI::Web::cust_fields, ], 'links' => [ $link, $link, - $link_cust, + ( map { $link_cust } + FS::UI::Web::cust_header() + ), ], ) %> diff --git a/httemplate/search/svc_forward.cgi b/httemplate/search/svc_forward.cgi index 1c1c6e4dd..330c0ee83 100755 --- a/httemplate/search/svc_forward.cgi +++ b/httemplate/search/svc_forward.cgi @@ -17,7 +17,8 @@ my $sql_query = { 'hashref' => {}, 'select' => join(', ', 'svc_forward.*', - map "cust_main.$_", qw(custnum last first company) + 'cust_main.custnum', + FS::UI::Web::cust_sql_fields(), ), 'extra_sql' => $orderby, 'addl_from' => 'LEFT JOIN cust_svc USING ( svcnum )'. @@ -75,7 +76,7 @@ my $link_cust = sub { $svc_x->custnum ? [ "${p}view/cust_main.cgi?", 'custnum' ] : ''; }; -%><%= include ('elements/search.html', +%><%= include( 'elements/search.html', 'title' => "Mail forward Search Results", 'name' => 'mail forwards', 'query' => $sql_query, @@ -84,17 +85,19 @@ my $link_cust = sub { 'header' => [ '#', 'Mail to', 'Forwards to', - 'Customer', + FS::UI::Web::cust_header(), ], 'fields' => [ 'svcnum', $format_src, $format_dst, - \&FS::svc_Common::cust_name, + \&FS::UI::Web::cust_fields, ], 'links' => [ $link, $link_src, $link_dst, - $link_cust, + ( map { $link_cust } + FS::UI::Web::cust_header() + ), ], - ) + ) %> diff --git a/httemplate/search/svc_www.cgi b/httemplate/search/svc_www.cgi index de1f5dd78..ae51c61fc 100755 --- a/httemplate/search/svc_www.cgi +++ b/httemplate/search/svc_www.cgi @@ -17,7 +17,8 @@ my $sql_query = { 'hashref' => {}, 'select' => join(', ', 'svc_www.*', - map "cust_main.$_", qw(custnum last first company) + 'cust_main.custnum', + FS::UI::Web::cust_sql_fields(), ), 'extra_sql' => $orderby, 'addl_from' => 'LEFT JOIN cust_svc USING ( svcnum )'. @@ -44,17 +45,25 @@ my $link_cust = sub { 'header' => [ '#', 'Zone', 'User', - 'Customer', + FS::UI::Web::cust_header(), ], 'fields' => [ 'svcnum', sub { $_[0]->domain_record->zone }, - sub { $_[0]->svc_acct->email }, - \&FS::svc_Common::cust_name, + sub { + my $svc_www = shift; + my $svc_acct = $svc_www->svc_acct; + $svc_acct + ? $svc_acct->email + : ''; + }, + \&FS::UI::Web::cust_fields, ], 'links' => [ $link, '', $ulink, - $link_cust, + ( map { $link_cust } + FS::UI::Web::cust_header() + ), ], ) %> -- 2.11.0