diff options
| author | Christopher Burger <burgerc@freeside.biz> | 2019-05-22 12:58:05 -0400 |
|---|---|---|
| committer | Christopher Burger <burgerc@freeside.biz> | 2019-05-22 21:17:32 -0400 |
| commit | 496ac38bb92a4ddb68318909c8b9d228ddda7bfb (patch) | |
| tree | b5ac0df05dcd82deb974d85e9d0257e11fa0229e | |
| parent | af1b255c779c5c6d0ddd354d670e6b909c26c4e3 (diff) | |
RT 77532 - added contact phone numbers to advanced customer report
Conflicts:
FS/FS/ConfDefaults.pm
FS/FS/cust_main.pm
FS/FS/cust_main/Search.pm
httemplate/elements/tr-select-cust-fields.html
httemplate/search/contact.html
| -rw-r--r-- | FS/FS/ConfDefaults.pm | 22 | ||||
| -rw-r--r-- | FS/FS/UI/Web.pm | 21 | ||||
| -rw-r--r-- | FS/FS/cust_main.pm | 25 | ||||
| -rw-r--r-- | FS/FS/cust_main/Search.pm | 19 | ||||
| -rw-r--r-- | httemplate/elements/select-cust-fields.html | 10 | ||||
| -rw-r--r-- | httemplate/elements/tr-select-cust-fields.html | 23 | ||||
| -rw-r--r-- | httemplate/search/elements/options_cust_contacts.html | 17 |
7 files changed, 91 insertions, 46 deletions
diff --git a/FS/FS/ConfDefaults.pm b/FS/FS/ConfDefaults.pm index 987225f42..f073252af 100644 --- a/FS/FS/ConfDefaults.pm +++ b/FS/FS/ConfDefaults.pm @@ -36,9 +36,9 @@ sub cust_fields_avail { ( 'Agent | Agent Cust# or Cust# | Cust. Status | Customer' => 'Agent | Agent Cust# | Status | Last, First or Company (Last, First)', - 'Customer | Day phone | Night phone | Mobile phone | Fax number' => + "Customer | Day phone | Night phone | Mobile phone | Fax number | Contact phone(s)" => 'Customer | (all phones)', - 'Cust# | Customer | Day phone | Night phone | Mobile phone | Fax number' => + 'Cust# | Customer | Day phone | Night phone | Mobile phone | Fax number | Contact phone(s)' => 'custnum | Customer | (all phones)', 'Cust. Status | Name | Company' => @@ -56,31 +56,31 @@ sub cust_fields_avail { ( 'Cust# | Cust. Status | Name | Company' => 'custnum | Status | Last, First | Company', - 'Cust# | Cust. Status | Name | Company | Address 1 | Address 2 | City | State | Zip | Country | Day phone | Night phone | Mobile phone | Fax number | Invoicing email(s)' => + 'Cust# | Cust. Status | Name | Company | Address 1 | Address 2 | City | State | Zip | Country | Day phone | Night phone | Mobile phone | Fax number | Contact phone(s) | Invoicing email(s)' => 'custnum | Status | Last, First | Company | (address) | (all phones) | Invoicing email(s)', - 'Cust# | Cust. Status | Name | Company | Address 1 | Address 2 | City | State | Zip | Country | Day phone | Night phone | Mobile phone | Fax number | Invoicing email(s) | Payment Type' => + 'Cust# | Cust. Status | Name | Company | Address 1 | Address 2 | City | State | Zip | Country | Day phone | Night phone | Mobile phone | Fax number | Contact phone(s) | Invoicing email(s) | Payment Type' => 'custnum | Status | Last, First | Company | (address) | (all phones) | Invoicing email(s) | Payment Type', - 'Cust# | Cust. Status | Name | Company | Address 1 | Address 2 | City | State | Zip | Country | Day phone | Night phone | Mobile phone | Fax number | Invoicing email(s) | Payment Type | Current Balance' => + 'Cust# | Cust. Status | Name | Company | Address 1 | Address 2 | City | State | Zip | Country | Day phone | Night phone | Mobile phone | Fax number | Contact phone(s) | Invoicing email(s) | Payment Type | Current Balance' => 'custnum | Status | Last, First | Company | (address) | (all phones) | Invoicing email(s) | Payment Type | Current Balance', - 'Cust# | Cust. Status | Name | Company | (bill) Address 1 | (bill) Address 2 | (bill) City | (bill) State | (bill) Zip | (bill) Country | Day phone | Night phone | Mobile phone | Fax number | (service) Address 1 | (service) Address 2 | (service) City | (service) State | (service) Zip | (service) Country | Invoicing email(s)' => + 'Cust# | Cust. Status | Name | Company | (bill) Address 1 | (bill) Address 2 | (bill) City | (bill) State | (bill) Zip | (bill) Country | Day phone | Night phone | Mobile phone | Fax number | Contact phone(s) | (service) Address 1 | (service) Address 2 | (service) City | (service) State | (service) Zip | (service) Country | Invoicing email(s)' => 'custnum | Status | Last, First | Company | (address) | (all phones) | (service address) | Invoicing email(s)', - 'Cust# | Cust. Status | Name | Company | (bill) Address 1 | (bill) Address 2 | (bill) City | (bill) State | (bill) Zip | (bill) Country | Day phone | Night phone | Mobile phone | Fax number | (service) Address 1 | (service) Address 2 | (service) City | (service) State | (service) Zip | (service) Country | Invoicing email(s) | Payment Type' => + 'Cust# | Cust. Status | Name | Company | (bill) Address 1 | (bill) Address 2 | (bill) City | (bill) State | (bill) Zip | (bill) Country | Day phone | Night phone | Mobile phone | Fax number | Contact phone(s) | (service) Address 1 | (service) Address 2 | (service) City | (service) State | (service) Zip | (service) Country | Invoicing email(s) | Payment Type' => 'custnum | Status | Last, First | Company | (address) | (all phones) | (service address) | Invoicing email(s) | Payment Type', - 'Cust# | Cust. Status | Name | Company | (bill) Address 1 | (bill) Address 2 | (bill) City | (bill) State | (bill) Zip | (bill) Country | Day phone | Night phone | Mobile phone | Fax number | (service) Address 1 | (service) Address 2 | (service) City | (service) State | (service) Zip | (service) Country | Invoicing email(s) | Payment Type | Current Balance' => + 'Cust# | Cust. Status | Name | Company | (bill) Address 1 | (bill) Address 2 | (bill) City | (bill) State | (bill) Zip | (bill) Country | Day phone | Night phone | Mobile phone | Fax number | Contact phone(s) | (service) Address 1 | (service) Address 2 | (service) City | (service) State | (service) Zip | (service) Country | Invoicing email(s) | Payment Type | Current Balance' => 'custnum | Status | Last, First | Company | (address) | (all phones) | (service address) | Invoicing email(s) | Payment Type | Current Balance', - 'Cust# | Agent Cust# | Cust. Status | Name | Company | (bill) Address 1 | (bill) Address 2 | (bill) City | (bill) State | (bill) Zip | (bill) Country | Day phone | Night phone | Mobile phone | Fax number | (service) Address 1 | (service) Address 2 | (service) City | (service) State | (service) Zip | (service) Country | Invoicing email(s) | Payment Type | Current Balance' => + 'Cust# | Agent Cust# | Cust. Status | Name | Company | (bill) Address 1 | (bill) Address 2 | (bill) City | (bill) State | (bill) Zip | (bill) Country | Day phone | Night phone | Mobile phone | Fax number | Contact phone(s) | (service) Address 1 | (service) Address 2 | (service) City | (service) State | (service) Zip | (service) Country | Invoicing email(s) | Payment Type | Current Balance' => 'custnum | Agent Cust# | Status | Last, First | Company | (address) | (all phones) | (service address) | Invoicing email(s) | Payment Type | Current Balance', - 'Cust# | Cust. Status | Name | Company | (bill) Address 1 | (bill) Address 2 | (bill) City | (bill) State | (bill) Zip | (bill) Country | (bill) Latitude | (bill) Longitude | Day phone | Night phone | Mobile phone | Fax number | (service) Address 1 | (service) Address 2 | (service) City | (service) State | (service) Zip | (service) Country | (service) Latitude | (service) Longitude | Invoicing email(s) | Payment Type | Current Balance' => + 'Cust# | Cust. Status | Name | Company | (bill) Address 1 | (bill) Address 2 | (bill) City | (bill) State | (bill) Zip | (bill) Country | (bill) Latitude | (bill) Longitude | Day phone | Night phone | Mobile phone | Fax number | Contact phone(s) | (service) Address 1 | (service) Address 2 | (service) City | (service) State | (service) Zip | (service) Country | (service) Latitude | (service) Longitude | Invoicing email(s) | Payment Type | Current Balance' => 'custnum | Status | Last, First | Company | (address+coord) | (all phones) | (service address+coord) | Invoicing email(s) | Payment Type | Current Balance', - 'Cust# | Cust. Status | Name | Company | (bill) Address 1 | (bill) Address 2 | (bill) City | (bill) State | (bill) Zip | (bill) Country | (bill) Latitude | (bill) Longitude | Day phone | Night phone | Mobile phone | Fax number | (service) Address 1 | (service) Address 2 | (service) City | (service) State | (service) Zip | (service) Country | (service) Latitude | (service) Longitude | Invoicing email(s) | Payment Type | Current Balance | Advertising Source' => + 'Cust# | Cust. Status | Name | Company | (bill) Address 1 | (bill) Address 2 | (bill) City | (bill) State | (bill) Zip | (bill) Country | (bill) Latitude | (bill) Longitude | Day phone | Night phone | Mobile phone | Fax number | Contact phone(s) | (service) Address 1 | (service) Address 2 | (service) City | (service) State | (service) Zip | (service) Country | (service) Latitude | (service) Longitude | Invoicing email(s) | Payment Type | Current Balance | Advertising Source' => 'custnum | Status | Last, First | Company | (address+coord) | (all phones) | (service address+coord) | Invoicing email(s) | Payment Type | Current Balance | Advertising Source', 'Invoicing email(s)' => 'Invoicing email(s)', diff --git a/FS/FS/UI/Web.pm b/FS/FS/UI/Web.pm index cdd7826c1..d5233f88b 100644 --- a/FS/FS/UI/Web.pm +++ b/FS/FS/UI/Web.pm @@ -7,7 +7,7 @@ use Carp qw( confess ); use HTML::Entities; use FS::Conf; use FS::Misc::DateTime qw( parse_datetime day_end ); -use FS::Record qw(dbdef); +use FS::Record qw(dbdef qsearch); use FS::cust_main; # are sql_balance and sql_date_balance in the right module? #use vars qw(@ISA); @@ -353,6 +353,25 @@ sub cust_header { $header2method{'Cust#'} = 'display_custnum' if $conf->exists('cust_main-default_agent_custid'); +foreach my $phone_type ( qsearch({table=>'phone_type', order_by=>'weight'}) ) { + $header2method{'Contact '.$phone_type->typename.' phone(s)'} = sub { + my $self = shift; + my $num = $phone_type->phonetypenum; + + my @phones; + foreach ($self->contact_list_name_phones) { + my $data = [ + { + 'data' => $_->first.' '.$_->last.' '.FS::contact_phone::phonenum_pretty($_), + }, + ]; + push @phones, $data if $_->phonetypenum eq $phone_type->phonetypenum; + } + return \@phones; + }; + +} + my %header2colormethod = ( 'Cust. Status' => 'cust_statuscolor', ); diff --git a/FS/FS/cust_main.pm b/FS/FS/cust_main.pm index 03300a075..2a3a753c0 100644 --- a/FS/FS/cust_main.pm +++ b/FS/FS/cust_main.pm @@ -3682,6 +3682,31 @@ sub contact_list_email { values %emails; } +=item contact_list_name_phones + +Returns a list of contact phone numbers. +{ phonetypenum => '1', phonenum => 'xxxxxxxxxx', first => 'firstname', last => 'lastname', countrycode => '1' } + +=cut + + sub contact_list_name_phones { + my $self = shift; + my $phone_type = shift; + + warn "$me contact_list_phones" if $DEBUG; + + return () if !$self->custnum; # not yet inserted + return map { $_ } + qsearch({ + table => 'contact', + select => 'phonetypenum, phonenum, first, last, countrycode', + addl_from => ' JOIN contact_phone USING (contactnum)', + hashref => { 'custnum' => $self->custnum, 'phonetypenum' => $phone_type, }, + order_by => 'ORDER BY contactnum DESC', + extra_sql => '', + }); + } + =item referral_custnum_cust_main Returns the customer who referred this customer (or the empty string, if diff --git a/FS/FS/cust_main/Search.pm b/FS/FS/cust_main/Search.pm index 7ee6a9302..fcb3efc3b 100644 --- a/FS/FS/cust_main/Search.pm +++ b/FS/FS/cust_main/Search.pm @@ -1095,25 +1095,24 @@ sub search { ) "; } - if ($contact_params->{'contacts_homephone'} || $contact_params->{'contacts_workphone'} || $contact_params->{'contacts_mobilephone'}) { - foreach my $phone (qw( contacts_homephone contacts_workphone contacts_mobilephone )) { + if ( grep { /^contacts_phonetypenum(\d+)$/ } keys %{ $contact_params } ) { + my $phone_query; + foreach my $phone ( grep { /^contacts_phonetypenum(\d+)$/ } keys %{ $contact_params } ) { + $phone =~ /^contacts_phonetypenum(\d+)$/ or die "No phone type num $1 from $phone"; + my $phonetypenum = $1; (my $num = $contact_params->{$phone}) =~ s/\W//g; if ( $num =~ /^1?(\d{3})(\d{3})(\d{4})(\d*)$/ ) { $contact_params->{$phone} = "$1$2$3"; } + $phone_query .= " AND ( contact_phone.phonetypenum = '".$phonetypenum."' AND contact_phone.phonenum = '" . $contact_params->{$phone} . "' )" + unless !$contact_params->{$phone}; } - my $home_query = " AND ( contact_phone.phonetypenum = '2' AND contact_phone.phonenum = '" . $contact_params->{'contacts_homephone'} . "' )" - unless !$contact_params->{'contacts_homephone'}; - my $work_query = " AND ( contact_phone.phonetypenum = '1' AND contact_phone.phonenum = '" . $contact_params->{'contacts_workphone'} . "' )" - unless !$contact_params->{'contacts_workphone'}; - my $mobile_query = " AND ( contact_phone.phonetypenum = '3' AND contact_phone.phonenum = '" . $contact_params->{'contacts_mobilephone'} . "' )" - unless !$contact_params->{'contacts_mobilephone'}; push @where, "EXISTS ( SELECT 1 FROM contact_phone JOIN contact USING (contactnum) WHERE contact.custnum = cust_main.custnum - $home_query $work_query $mobile_query + $phone_query ) "; } -} + } ## diff --git a/httemplate/elements/select-cust-fields.html b/httemplate/elements/select-cust-fields.html index 5e3063877..7396808b1 100644 --- a/httemplate/elements/select-cust-fields.html +++ b/httemplate/elements/select-cust-fields.html @@ -1,8 +1,14 @@ <%init> my( $cust_fields, %opt ) = @_; - use FS::ConfDefaults; - $opt{'avail_fields'} ||= [ FS::ConfDefaults->cust_fields_avail() ]; + my @fields = FS::ConfDefaults->cust_fields_avail(); + my $contact_phone_list; + foreach my $phone_type ( qsearch({table=>'phone_type', order_by=>'weight'}) ) { + $contact_phone_list .= " | Contact ".$phone_type->typename." phone(s)"; + } + @fields = map {s/\| Contact phone\(s\)/$contact_phone_list/g; $_; } @fields; + + $opt{'avail_fields'} ||= [ @fields ]; tie my %hash, 'Tie::IxHash', @{ $opt{'avail_fields'} }; </%init> diff --git a/httemplate/elements/tr-select-cust-fields.html b/httemplate/elements/tr-select-cust-fields.html index 80562fe3d..d3786d270 100644 --- a/httemplate/elements/tr-select-cust-fields.html +++ b/httemplate/elements/tr-select-cust-fields.html @@ -1,15 +1,20 @@ -% -% my( $cust_fields, %opt ) = @_; -% -% use FS::ConfDefaults; -% $opt{'avail_fields'} ||= [ FS::ConfDefaults->cust_fields_avail() ]; -% -% - - <TR> <TD ALIGN="right"><% $opt{'label'} || 'Customer fields' %></TD> <TD> <% include( '/elements/select-cust-fields.html', $cust_fields, %opt ) %> </TD> </TR> +<%init> + +my( $cust_fields, %opt ) = @_; + +my @fields = FS::ConfDefaults->cust_fields_avail(); +my $contact_phone_list; +foreach my $phone_type ( qsearch({table=>'phone_type', order_by=>'weight'}) ) { + $contact_phone_list .= " | Contact ".$phone_type->typename." phone(s)"; +} +@fields = map {s/\| Contact phone\(s\)/$contact_phone_list/g; $_; } @fields; + +$opt{'avail_fields'} ||= [ @fields ]; + +</%init> diff --git a/httemplate/search/elements/options_cust_contacts.html b/httemplate/search/elements/options_cust_contacts.html index cfbf834b0..8a6b76913 100644 --- a/httemplate/search/elements/options_cust_contacts.html +++ b/httemplate/search/elements/options_cust_contacts.html @@ -12,21 +12,12 @@ <TH ALIGN="right" VALIGN="center"><% mt('Email') |h %></TH> <TD><INPUT TYPE="text" NAME="<%$field_prefix%>email" SIZE=54></TD> </TR> - - <TR> - <TH ALIGN="right" VALIGN="center"><% mt('Home Phone') |h %></TH> - <TD><INPUT TYPE="text" NAME="<%$field_prefix%>homephone" SIZE=54></TD> - </TR> - - <TR> - <TH ALIGN="right" VALIGN="center"><% mt('Work Phone') |h %></TH> - <TD><INPUT TYPE="text" NAME="<%$field_prefix%>workphone" SIZE=54></TD> - </TR> - +% foreach my $phone_type ( qsearch({table=>'phone_type', order_by=>'weight'}) ) { <TR> - <TH ALIGN="right" VALIGN="center"><% mt('Mobile Phone') |h %></TH> - <TD><INPUT TYPE="text" NAME="<%$field_prefix%>mobilephone" SIZE=54></TD> + <TH ALIGN="right" VALIGN="center"><% $phone_type->typename. ' Phone' |h %></TH> + <TD><INPUT TYPE="text" NAME="<% $field_prefix %>phonetypenum<% $phone_type->phonetypenum %>" SIZE=54></TD> </TR> +% } <%init> |
