add city search, RT#31659
authorIvan Kohler <ivan@freeside.biz>
Wed, 7 Jan 2015 22:30:16 +0000 (14:30 -0800)
committerIvan Kohler <ivan@freeside.biz>
Wed, 7 Jan 2015 22:30:16 +0000 (14:30 -0800)
FS/FS/cust_main/Search.pm
httemplate/elements/city.html
httemplate/elements/select-country.html
httemplate/elements/select-county.html
httemplate/search/cust_main.html
httemplate/search/report_cust_main.html

index e0dfc3c..a8f9791 100644 (file)
@@ -727,6 +727,18 @@ sub search {
   }
 
   ##
+  # city
+  ##
+  if ( $params->{'city'} =~ /\S/ ) {
+    my $city = dbh->quote($params->{'city'});
+    push @where, "EXISTS(
+      SELECT 1 FROM cust_location
+      WHERE cust_location.custnum = cust_main.custnum
+        AND cust_location.city = $city
+    )";
+  }
+
+  ##
   # county
   ##
   if ( $params->{'county'} =~ /\S/ ) {
index 6a2142f..5f4d4e0 100644 (file)
@@ -2,22 +2,24 @@
 
 Example:
 
-  include( '/elements/city.html',
-    #recommended
-    country    => $current_country,
-    state      => $current_state,
-    county     => $current_county,
-    city       => $current_city,
-
-    #optional
-    prefix        => $optional_unique_prefix,
-    onchange      => $javascript,
-    disabled      => 0, #bool
-#    disable_empty => 1, #defaults to 1, disable the empty option
-#    empty_label   => 'all', #label for empty option
-#    disable_select => 1, # disable the selector (just show a text input)
-    style         => [ 'attribute:value', 'another:value' ],
-  );
+  <& /elements/city.html,
+       #recommended
+       country        => $current_country,
+       state          => $current_state,
+       county         => $current_county,
+       city           => $current_city,
+
+       #optional
+       prefix         => $optional_unique_prefix,
+       onchange       => $javascript,
+       disabled       => 0, #bool
+       style          => [ 'attribute:value', 'another:value' ],
+       disable_empty  => 1, #defaults to 1, set to 0 to disable the empty option
+       empty_label    => 'all', #label for empty option
+       disable_text   => 1, # disable the text input (just show the select)
+       #doesn't work as an option yet, set when conf tax_district_method
+       #disable_select => 1, # disable the selector (just show a text input)
+  &>
 
 </%doc>
 
@@ -47,16 +49,22 @@ function <% $pre %>county_changed(what, callback) {}
 
   function <% $pre %>county_changed(what, callback) {
 
+    what.form.<% $pre %>city_select.disabled = 'disabled';
+
     county  = what.options[what.selectedIndex].value;
     state   = what.form.<% $pre %>state.options[what.form.<% $pre %>state.selectedIndex].value;
     country = what.form.<% $pre %>country.options[what.form.<% $pre %>country.selectedIndex].value;
 
     function <% $pre %>update_cities(cities) {
-     
+
       // blank the current city list
       for ( var i = what.form.<% $pre %>city_select.length; i >= 0; i-- )
           what.form.<% $pre %>city_select.options[i] = null;
 
+%     unless ( $opt{disable_empty} ) {
+        opt( what.form.<% $pre %>city_select, '', <% $opt{empty_label} |js_string %> );
+%     }
+
       // add the new cities
       var citiesArray = eval('(' + cities + ')' );
 
@@ -67,7 +75,7 @@ function <% $pre %>county_changed(what, callback) {}
           opt(what.form.<% $pre %>city_select, citiesArray[s], cityLabel);
       }
 
-     if ( citiesArray.length > 1 || citiesArray[0].length ) { 
+     if ( citiesArray.length > 1 || (citiesArray[0] && citiesArray[0].length) ){
         // turn off the text city, turn on the select
         saved_<%$pre%>city = what.form.<%$ pre %>city.value;
         <%$pre%>city_select_changed(what.form.<% $pre %>city_select);
@@ -80,6 +88,8 @@ function <% $pre %>county_changed(what, callback) {}
         what.form.<% $pre %>city_select.style.display = 'none';
       }
 
+      what.form.<% $pre %>city_select.disabled = '';
+
       //run the callback
       if ( callback != null )
         callback();
@@ -98,39 +108,44 @@ function <% $pre %>county_changed(what, callback) {}
 
 % } #!disable_select
 
-<INPUT TYPE     = "text"
+<INPUT TYPE     = "<% $opt{disable_text} ? 'hidden' : 'text' %>"
        NAME     = "<%$pre%>city"
        ID       = "<%$pre%>city"
        VALUE    = "<% $opt{'city'} |h %>"
+% unless ( $opt{disable_text} ) {
        onChange = "<% $opt{'onchange'} %>"
        <% $opt{'disabled'} %>
        <% $text_style %>
+% }
 >
 
 % if ( $disable_select ) {
 %# avoid JS errors
-<INPUT TYPE="hidden" ID="city_select">
-% }
-% else {
+    <INPUT TYPE="hidden" ID="city_select">
+% } else {
 
-<SELECT NAME     = "<%$pre%>city_select"
-        ID       = "<%$pre%>city_select"
-        onChange = "<%$pre%>city_select_changed(this); <% $opt{'onchange'} %>"
-        <% $opt{'disabled'} %>
-        <% $select_style %>
->
+    <SELECT NAME     = "<%$pre%>city_select"
+            ID       = "<%$pre%>city_select"
+            onChange = "<%$pre%>city_select_changed(this); <% $opt{onchange} %>"
+            <% $opt{disabled} %>
+            <% $select_style %>
+    >
 
-% foreach my $city ( @cities ) {
+%   unless ( $opt{'disable_empty'} ) {
+      <OPTION VALUE="" <% $opt{city} eq '' ? 'SELECTED' : '' %>><% $opt{empty_label} %>
+%   }
 
-    <OPTION VALUE="<% $city |h %>"
-            <% $city eq $opt{'city'} ? 'SELECTED' : '' %>
-    ><% $city eq $opt{'empty_data_value'} ? $opt{'empty_data_label'} : $city %>
+%   foreach my $city ( @cities ) {
 
-% }
+      <OPTION VALUE="<% $city |h %>"
+              <% $city eq $opt{city} ? 'SELECTED' : '' %>
+      ><% $city eq $opt{empty_data_value} ? $opt{empty_data_label} : $city %>
 
-</SELECT>
+%   }
+
+    </SELECT>
 % }
-%#           VALUE    = "<% $curr_value |h %>"
+
 <%init>
 
 my %opt = @_;
@@ -142,6 +157,8 @@ my $conf = new FS::Conf;
 # tax district table.
 my $disable_select = 1 if $conf->config('tax_district_method');
 
+$opt{'disable_empty'} = 1 unless exists($opt{'disable_empty'});
+
 my $text_style   = $opt{'style'} ? [ @{ $opt{'style'} } ] : [];
 my $select_style = $opt{'style'} ? [ @{ $opt{'style'} } ] : [];
 
index 724afe3..f3d9876 100644 (file)
@@ -40,6 +40,8 @@ Example:
     }
   
     function <% $pre %>country_changed(what, callback) {
+
+      what.form.<% $pre %>state.disabled = 'disabled';
   
       country = what.options[what.selectedIndex].value;
   
@@ -61,6 +63,8 @@ Example:
                 stateLabel = <% $opt{state_empty_label} || '(n/a)' |js_string %>;
             opt(what.form.<% $pre %>state, statesArray[s], stateLabel);
         }
+
+        what.form.<% $pre %>state.disabled = '';
   
         //run the callback
         if ( callback != null ) {
index 6d498be..f72eb6a 100644 (file)
@@ -12,7 +12,7 @@ Example:
     prefix        => $optional_unique_prefix,
     onchange      => $javascript,
     disabled      => 0, #bool
-    disable_empty => 1, #defaults to 1, disable the empty option
+    disable_empty => 1, #defaults to 1, set to 0 to disable the empty option
     empty_label   => 'all', #label for empty option
     style         => [ 'attribute:value', 'another:value' ],
   );
@@ -36,6 +36,8 @@ Example:
   
     function <% $pre %>state_changed(what, callback) {
 
+      what.form.<% $pre %>county.disabled = 'disabled';
+
       state = what.options[what.selectedIndex].value;
       country = what.form.<% $pre %>country.options[what.form.<% $pre %>country.selectedIndex].value;
   
@@ -44,6 +46,10 @@ Example:
         // blank the current county list
         for ( var i = what.form.<% $pre %>county.length; i >= 0; i-- )
             what.form.<% $pre %>county.options[i] = null;
+
+%       unless ( $opt{disable_empty} ) {
+          opt( what.form.<% $pre %>county, '', <% $opt{empty_label} |js_string %> );
+%       }
   
         // add the new counties
         var countiesArray = eval('(' + counties + ')' );
@@ -58,14 +64,20 @@ Example:
 
         if ( countiesArray.length > 1 ) { 
           what.form.<% $pre %>county.style.display = '';
-          //countyFormLabel.style.visibility = 'visible';
-          countyFormLabel.style.display = '';
+          if ( countyFormLabel )  {
+            //countyFormLabel.style.visibility = 'visible';
+            countyFormLabel.style.display = '';
+          }
         } else {
           what.form.<% $pre %>county.style.display = 'none';
-          //countyFormLabel.style.visibility = 'hidden';
-          countyFormLabel.style.display = 'none';
+          if ( countyFormLabel ) {
+            //countyFormLabel.style.visibility = 'hidden';
+            countyFormLabel.style.display = 'none';
+          }
         }
 
+        what.form.<% $pre %>county.disabled = '';
+
         //run the callback
         if ( callback != null )  {
           callback();
index 19456e6..503e782 100755 (executable)
@@ -41,7 +41,7 @@ my %search_hash = ();
 
 #scalars
 my @scalars = qw (
-  agentnum salesnum status address county state zip country
+  agentnum salesnum status address city county state zip country
   paydate_year paydate_month invoice_terms
   no_censustract with_geocode with_email tax no_tax POST no_POST
   custbatch usernum
index 2b40672..cacb7de 100755 (executable)
@@ -6,7 +6,7 @@
   <TABLE BGCOLOR="#cccccc" CELLSPACING=0>
 
     <TR>
-      <TH CLASS="background" COLSPAN=2 ALIGN="left"><FONT SIZE="+1"><% mt('Search options') |h %></FONT></TH>
+      <TH CLASS="background" COLSPAN=2 ALIGN="left"><FONT SIZE="+1"><% mt('Basic search options') |h %></FONT></TH>
     </TR>
 
     <& /elements/tr-select-agent.html,
     &>
 
     <TR>
-      <TD ALIGN="right" VALIGN="center"><% mt('Address') |h %></TD>
-      <TD><INPUT TYPE="text" NAME="address" SIZE=54></TD>
-    </TR>
-
-    <TR>
-      <TD ALIGN="right" VALIGN="center"><% mt('County') |h %></TD>
-      <TD>
-        <& /elements/select-county.html,
-             disable_empty => 0,
-             empty_label   => '(all)',
-        &>
-      </TD>
-    </TR>
-    
-
-    <TR>
-      <TD ALIGN="right" VALIGN="center"><% mt('State') |h %></TD>
-      <TD>
-        <& /elements/select-state.html,
-             disable_empty => 0,
-             empty_label   => '(all)',
-        &>
-      </TD>
-    </TR>
-    
-    <TR>
-      <TD ALIGN="right" VALIGN="center"><% mt('Zip') |h %></TD>
-      <TD><INPUT TYPE="text" NAME="zip" SIZE=12></TD>
-    </TR>
-
-    <TR>
-      <TD ALIGN="right" VALIGN="center"><% mt('Country') |h %></TD>
-      <TD>
-        <& /elements/select-country.html,
-             disable_empty       => 0,
-             state_disable_empty => 0,
-             state_empty_label   => '(all)',
-        &>
-      </TD>
-    </TR>
-
-    <TR>
         <TD ALIGN="right" VALIGN="center"><% mt('Signup date') |h %></TD>
         <TD>
         <TABLE>
         </TD>
       </TR>
 
+    <TR>
+      <TH CLASS="background" COLSPAN=2>&nbsp;</TH>
+    </TR>
+
+    <TR>
+      <TH CLASS="background" COLSPAN=2 ALIGN="left"><FONT SIZE="+1"><% mt('Location search options') |h %></FONT></TH>
+    </TR>
+
+    <TR>
+      <TD ALIGN="right" VALIGN="center"><% mt('Address') |h %></TD>
+      <TD><INPUT TYPE="text" NAME="address" SIZE=54></TD>
+    </TR>
+
+    <TR>
+      <TD ALIGN="right" VALIGN="center"><% mt('City') |h %></TD>
+      <TD>
+        <& /elements/city.html,
+             disable_empty => 0,
+             empty_label   => '(all)',
+             disable_text  => 1,
+        &>
+      </TD>
+    </TR>
+
+    <TR>
+      <TD ALIGN="right" VALIGN="center"><% mt('County') |h %></TD>
+      <TD>
+        <& /elements/select-county.html,
+             disable_empty => 0,
+             empty_label   => '(all)',
+        &>
+      </TD>
+    </TR>
+    
+    <TR>
+      <TD ALIGN="right" VALIGN="center"><% mt('State') |h %></TD>
+      <TD>
+        <& /elements/select-state.html,
+             disable_empty => 0,
+             empty_label   => '(all)',
+        &>
+      </TD>
+    </TR>
+    
+    <TR>
+      <TD ALIGN="right" VALIGN="center"><% mt('Zip') |h %></TD>
+      <TD><INPUT TYPE="text" NAME="zip" SIZE=12></TD>
+    </TR>
+
+    <TR>
+      <TD ALIGN="right" VALIGN="center"><% mt('Country') |h %></TD>
+      <TD>
+        <& /elements/select-country.html,
+             disable_empty       => 0,
+             state_disable_empty => 0,
+             state_empty_label   => '(all)',
+        &>
+      </TD>
+    </TR>
+
+    <TR>
+      <TH CLASS="background" COLSPAN=2>&nbsp;</TH>
+    </TR>
+
+    <TR>
+      <TH CLASS="background" COLSPAN=2 ALIGN="left"><FONT SIZE="+1"><% mt('Billing search options') |h %></FONT></TH>
+    </TR>
+
     <& /elements/tr-select-payby.html,
                   'payby_type'   => 'cust',
                   'multiple'     => 1,
     &>
 
     <TR>
-      <TD ALIGN="right" VALIGN="center"><% mt('With email address(es)') |h %></TD>
+      <TD ALIGN="right" VALIGN="center"><% mt('With invoicing email address(es)') |h %></TD>
         <TD><INPUT TYPE="checkbox" NAME="with_email"></TD>
     </TR>