add cust_main-require_address2 config, reimplement address2-search config ("Unit...
authorivan <ivan>
Mon, 17 Dec 2007 00:59:02 +0000 (00:59 +0000)
committerivan <ivan>
Mon, 17 Dec 2007 00:59:02 +0000 (00:59 +0000)
FS/FS/Conf.pm
FS/FS/cust_main.pm
httemplate/edit/cust_main.cgi
httemplate/edit/cust_main/billing.html
httemplate/edit/cust_main/contact.html
httemplate/elements/header.html
httemplate/search/cust_main.cgi
httemplate/view/cust_main/contacts.html

index 0f1fcbb..85a2b9b 100644 (file)
@@ -1716,7 +1716,14 @@ worry that config_items is freeside-specific and icky.
   {
     'key'         => 'address2-search',
     'section'     => 'UI',
-    'description' => 'Enable a "Unit" search box which searches the second address field',
+    'description' => 'Enable a "Unit" search box which searches the second address field.  Useful for multi-tenant applications.  See also: cust_main-require_address2',
+    'type'        => 'checkbox',
+  },
+
+  {
+    'key'         => 'cust_main-require_address2',
+    'section'     => 'UI',
+    'description' => 'Second address field is required (on service address only, if billing and service addresses differ).  Also enables "Unit" labeling of address2 on customer view and edit pages.  Useful for multi-tenant applications.  See also: address2-search',
     'type'        => 'checkbox',
   },
 
@@ -2091,7 +2098,7 @@ worry that config_items is freeside-specific and icky.
   {
     'key'         => 'cust_main-require_invoicing_list_email',
     'section'     => '',
-    'description' => 'Require at least one invoicing email address for all customer records.',
+    'description' => 'Email address field is required: require at least one invoicing email address for all customer records.',
     'type'        => 'checkbox',
   },
 
index 59ebfb5..b5e6892 100644 (file)
@@ -1291,58 +1291,60 @@ sub check {
   
   }
 
-  my @addfields = qw(
-    last first company address1 address2 city county state zip
-    country daytime night fax
-  );
+  if ( $self->has_ship_address
+       && scalar ( grep { $self->getfield($_) ne $self->getfield("ship_$_") }
+                        $self->addr_fields )
+     )
+  {
+    my $error =
+      $self->ut_name('ship_last')
+      || $self->ut_name('ship_first')
+      || $self->ut_textn('ship_company')
+      || $self->ut_text('ship_address1')
+      || $self->ut_textn('ship_address2')
+      || $self->ut_text('ship_city')
+      || $self->ut_textn('ship_county')
+      || $self->ut_textn('ship_state')
+      || $self->ut_country('ship_country')
+    ;
+    return $error if $error;
 
-  if ( defined $self->dbdef_table->column('ship_last') ) {
-    if ( scalar ( grep { $self->getfield($_) ne $self->getfield("ship_$_") }
-                       @addfields )
-         && scalar ( grep { $self->getfield("ship_$_") ne '' } @addfields )
-       )
-    {
-      my $error =
-        $self->ut_name('ship_last')
-        || $self->ut_name('ship_first')
-        || $self->ut_textn('ship_company')
-        || $self->ut_text('ship_address1')
-        || $self->ut_textn('ship_address2')
-        || $self->ut_text('ship_city')
-        || $self->ut_textn('ship_county')
-        || $self->ut_textn('ship_state')
-        || $self->ut_country('ship_country')
-      ;
-      return $error if $error;
+    #false laziness with above
+    unless ( qsearchs('cust_main_county', {
+      'country' => $self->ship_country,
+      'state'   => '',
+     } ) ) {
+      return "Unknown ship_state/ship_county/ship_country: ".
+        $self->ship_state. "/". $self->ship_county. "/". $self->ship_country
+        unless qsearch('cust_main_county',{
+          'state'   => $self->ship_state,
+          'county'  => $self->ship_county,
+          'country' => $self->ship_country,
+        } );
+    }
+    #eofalse
 
-      #false laziness with above
-      unless ( qsearchs('cust_main_county', {
-        'country' => $self->ship_country,
-        'state'   => '',
-       } ) ) {
-        return "Unknown ship_state/ship_county/ship_country: ".
-          $self->ship_state. "/". $self->ship_county. "/". $self->ship_country
-          unless qsearch('cust_main_county',{
-            'state'   => $self->ship_state,
-            'county'  => $self->ship_county,
-            'country' => $self->ship_country,
-          } );
-      }
-      #eofalse
-
-      $error =
-        $self->ut_phonen('ship_daytime', $self->ship_country)
-        || $self->ut_phonen('ship_night', $self->ship_country)
-        || $self->ut_phonen('ship_fax', $self->ship_country)
-        || $self->ut_zip('ship_zip', $self->ship_country)
-      ;
-      return $error if $error;
+    $error =
+      $self->ut_phonen('ship_daytime', $self->ship_country)
+      || $self->ut_phonen('ship_night', $self->ship_country)
+      || $self->ut_phonen('ship_fax', $self->ship_country)
+      || $self->ut_zip('ship_zip', $self->ship_country)
+    ;
+    return $error if $error;
+
+    return "Unit # is required."
+      if $self->ship_address2 =~ /^\s*$/
+      && $conf->exists('cust_main-require_address2');
+
+  } else { # ship_ info eq billing info, so don't store dup info in database
+
+    $self->setfield("ship_$_", '')
+      foreach $self->addr_fields;
+
+    return "Unit # is required."
+      if $self->address2 =~ /^\s*$/
+      && $conf->exists('cust_main-require_address2');
 
-    } else { # ship_ info eq billing info, so don't store dup info in database
-      $self->setfield("ship_$_", '')
-        foreach qw( last first company address1 address2 city county state zip
-                    country daytime night fax );
-    }
   }
 
   #$self->payby =~ /^(CARD|DCRD|CHEK|DCHK|LECB|BILL|COMP|PREPAY|CASH|WEST|MCRD)$/
@@ -1543,6 +1545,30 @@ sub check {
   $self->SUPER::check;
 }
 
+=item addr_fields 
+
+Returns a list of fields which have ship_ duplicates.
+
+=cut
+
+sub addr_fields {
+  qw( last first company
+      address1 address2 city county state zip country
+      daytime night fax
+    );
+}
+
+=item has_ship_address
+
+Returns true if this customer record has a separate shipping address.
+
+=cut
+
+sub has_ship_address {
+  my $self = shift;
+  scalar( grep { $self->getfield("ship_$_") ne '' } $self->addr_fields );
+}
+
 =item all_pkgs
 
 Returns all packages (see L<FS::cust_pkg>) for this customer.
index 579d6cf..be9dd1b 100755 (executable)
 
 <!-- contact info -->
 
+%  my $same_checked = '';
+%  my $ship_disabled = '';
+%  unless ( $cust_main->ship_last && $same ne 'Y' ) {
+%    $same_checked = 'CHECKED';
+%    $ship_disabled = 'DISABLED STYLE="background-color: #dddddd"';
+%    foreach (
+%      qw( last first company address1 address2 city county state zip country
+%          daytime night fax )
+%    ) {
+%      $cust_main->set("ship_$_", $cust_main->get($_) );
+%    }
+%  }
+
 <BR><BR>
 Billing address
-<% include('cust_main/contact.html', $cust_main, '', 'bill_changed(this)', '', 'ss' => $ss, 'stateid' => $stateid ) %>
-
-<!-- service address -->
-% if ( defined $cust_main->dbdef_table->column('ship_last') ) { 
-
+<% include('cust_main/contact.html',
+             'cust_main'    => $cust_main,
+             'pre'          => '',
+             'onchange'     => 'bill_changed(this)',
+             'disabled'     => '',
+             'ss'           => $ss,
+             'stateid'      => $stateid,
+             'same_checked' => $same_checked, #for address2 "Unit #" labeling
+          )
+%>
 
 <SCRIPT>
 function bill_changed(what) {
@@ -241,44 +259,47 @@ function bill_changed(what) {
 function samechanged(what) {
   if ( what.checked ) {
     bill_changed(what);
-% for (qw( last first company address1 address2 city county state zip country daytime night fax )) { 
 
-    what.form.ship_<%$_%>.disabled = true;
-    what.form.ship_<%$_%>.style.backgroundColor = '#dddddd';
-% } 
+%   for (qw( last first company address1 address2 city county state zip country daytime night fax )) { 
+      what.form.ship_<%$_%>.disabled = true;
+      what.form.ship_<%$_%>.style.backgroundColor = '#dddddd';
+%   } 
+
+%   if ( $conf->exists('cust_main-require_address2') ) {
+      document.getElementById('address2_required').style.visibility = '';
+      document.getElementById('address2_label').style.visibility = '';
+      document.getElementById('ship_address2_required').style.visibility = 'hidden';
+      document.getElementById('ship_address2_label').style.visibility = 'hidden';
+%   }
 
   } else {
-% for (qw( last first company address1 address2 city county state zip country daytime night fax )) { 
 
-    what.form.ship_<%$_%>.disabled = false;
-    what.form.ship_<%$_%>.style.backgroundColor = '#ffffff';
-% } 
+%   for (qw( last first company address1 address2 city county state zip country daytime night fax )) { 
+      what.form.ship_<%$_%>.disabled = false;
+      what.form.ship_<%$_%>.style.backgroundColor = '#ffffff';
+%   } 
+
+%   if ( $conf->exists('cust_main-require_address2') ) {
+      document.getElementById('address2_required').style.visibility = 'hidden';
+      document.getElementById('address2_label').style.visibility = 'hidden';
+      document.getElementById('ship_address2_required').style.visibility = '';
+      document.getElementById('ship_address2_label').style.visibility = '';
+%   }
 
   }
 }
 </SCRIPT>
-%
-%  my $checked = '';
-%  my $disabled = '';
-%  my $disabledselect = '';
-%  unless ( $cust_main->ship_last && $same ne 'Y' ) {
-%    $checked = 'CHECKED';
-%    $disabled = 'DISABLED STYLE="background-color: #dddddd"';
-%    foreach (
-%      qw( last first company address1 address2 city county state zip country
-%          daytime night fax )
-%    ) {
-%      $cust_main->set("ship_$_", $cust_main->get($_) );
-%    }
-%  }
-%
-
 
 <BR>
 Service address 
-(<INPUT TYPE="checkbox" NAME="same" VALUE="Y" onClick="samechanged(this)" <%$checked%>>same as billing address)
-<% include('cust_main/contact.html', $cust_main, 'ship_', '', $disabled ) %>
-% } 
+(<INPUT TYPE="checkbox" NAME="same" VALUE="Y" onClick="samechanged(this)" <%$same_checked%>>same as billing address)
+<% include('cust_main/contact.html',
+             'cust_main' => $cust_main,
+             'pre'       => 'ship_',
+             'onchange'  => '',
+             'disabled'  => $ship_disabled,
+          )
+%>
 
 
 <!-- billing info -->
index 394c5d8..6ed35c1 100644 (file)
 % }
 
     <TR>
-      <TD ALIGN="right" WIDTH="200">Email invoice </TD>
+      <TD ALIGN="right" WIDTH="200">
+        <% $conf->exists('cust_main-require_invoicing_list_email') ? $r : '' %>Email address(es)
+      </TD>
       <TD WIDTH="408"><INPUT TYPE="text" NAME="invoicing_list" VALUE="<% join(', ', grep { $_ !~ /^(POST|FAX)$/ } @invoicing_list ) %>"></TD>
     </TR>
 
index 58fee32..21c6b29 100644 (file)
   </TD>
 </TR>
 
+% my $address2_label_style =
+%   ( $disabled
+%     || ! $conf->exists('cust_main-require_address2')
+%     || ( !$pre && !$opt{'same_checked'} )
+%   )
+%     ? 'visibility:hidden'
+%     : '';
+
 <TR>
-  <TD ALIGN="right">&nbsp;</TD>
+  <TD ALIGN="right"><FONT ID="<% $pre %>address2_required" color="#ff0000" STYLE="<% $address2_label_style %>">*</FONT>&nbsp;<FONT ID="<% $pre %>address2_label" STYLE="<% $address2_label_style %>"><B>Unit&nbsp;#</B></FONT></TD>
   <TD COLSPAN=7>
     <INPUT TYPE="text" NAME="<%$pre%>address2" VALUE="<% $cust_main->get($pre.'address2') %>" SIZE=70 onChange="<% $onchange %>" <%$disabled%>>
   </TD>
 
 <%init>
 
-my( $cust_main, $pre, $onchange, $disabled, %opt ) = @_;
+#my( $cust_main, $pre, $onchange, $disabled, %opt ) = @_;
+my %opt = @_;
+my $cust_main = $opt{'cust_main'};
+my $pre       = $opt{'pre'};
+my $onchange  = $opt{'onchange'};
+my $disabled  = $opt{'disabled'};
+
 my $conf = new FS::Conf;
 
 foreach (qw(ss stateid)) {
index 0ff8ecd..dfe6b68 100644 (file)
           what.value = '';
       }
 
+      function clearhint_search_address2 (what) {
+        if ( what.value == '(Unit #)' )
+          what.value = '';
+      }
+
       function clearhint_search_invoice (what) {
         if ( what.value == '(inv #)' )
           what.value = '';
@@ -113,14 +118,14 @@ input.fsblackbuttonselected {
 
     <TABLE WIDTH="100%" CELLSPACING=0 CELLPADDING=0>
       <TR>
-        <TD COLSPAN=5 WIDTH="100%" STYLE="padding:0"><IMG BORDER=0 ALT="" SRC="<%$fsurl%>images/black-gradient.png" HEIGHT="13" WIDTH="100%"></TD>
+        <TD COLSPAN=6 WIDTH="100%" STYLE="padding:0"><IMG BORDER=0 ALT="" SRC="<%$fsurl%>images/black-gradient.png" HEIGHT="13" WIDTH="100%"></TD>
       </TR>
 
 % if ( $menu_position eq 'top' ) {
 
       <TR>
 
-        <TD COLSPAN="5" WIDTH="100%" STYLE="padding:0">
+        <TD COLSPAN="6" WIDTH="100%" STYLE="padding:0">
           <SCRIPT TYPE="text/javascript">
             document.write(myBar);
           </SCRIPT>
@@ -129,12 +134,12 @@ input.fsblackbuttonselected {
       </TR>
 
       <TR>
-        <TD COLSPAN="5" WIDTH="100%" HEIGHT="2px" STYLE="padding:0" BGCOLOR="#000000">
+        <TD COLSPAN="6" WIDTH="100%" HEIGHT="2px" STYLE="padding:0" BGCOLOR="#000000">
         </TD>
       </TR>
       
       <TR>
-        <TD COLSPAN="5" WIDTH="100%" HEIGHT="4px" STYLE="padding:0" BGCOLOR="#000000">
+        <TD COLSPAN="6" WIDTH="100%" HEIGHT="4px" STYLE="padding:0" BGCOLOR="#000000">
         </TD>
       </TR>
 
@@ -156,21 +161,31 @@ input.fsblackbuttonselected {
           </FORM>
         </TD>
 
+        <TD COLSPAN=1 BGCOLOR="#000000" ALIGN="center">
+% if ( $conf->exists('address2-search') ) { 
+            <FORM ACTION="<%$fsurl%>search/cust_main.cgi" METHOD="GET" STYLE="margin:0;display:inline">
+              <INPUT TYPE="hidden" NAME="address2_on" VALUE="1">
+              <INPUT NAME="address2_text" TYPE="text" VALUE="(Unit #)" SIZE="4" onFocus="clearhint_search_address2(this);" onClick="clearhint_search_address2(this);" STYLE="vertical-align:bottom;text-align:right;margin-bottom:1px">
+              <BR>
+              <INPUT TYPE="submit" VALUE="Search units" CLASS="fsblackbutton" onMouseOver="this.className='fsblackbuttonselected'; return true;" onMouseOut="this.className='fsblackbutton'; return true;" STYLE="font-size:70%;padding-left:2px;padding-right:2px">
+            </FORM>
+% } 
+        </TD>
+
         <TD COLSPAN=1 BGCOLOR="#000000" ALIGN="right">
 % if ( $FS::CurrentUser::CurrentUser->access_right('View invoices') ) { 
 
             <FORM ACTION="<%$fsurl%>search/cust_bill.html" METHOD="GET" STYLE="margin:0;display:inline">
               <INPUT NAME="invnum" TYPE="text" VALUE="(inv #)" SIZE="4" onFocus="clearhint_search_invoice(this);" onClick="clearhint_search_invoice(this);" STYLE="vertical-align:bottom;text-align:right;margin-bottom:1px">
-% if ( $FS::CurrentUser::CurrentUser->access_right('List invoices') ) { 
+%   if ( $FS::CurrentUser::CurrentUser->access_right('List invoices') ) { 
 
                 <A HREF="<%$fsurl%>search/report_cust_bill.html" STYLE="color: #ffffff; font-size: 70%">Advanced</A>
-% } 
+%   
 
               <BR>
               <INPUT TYPE="submit" VALUE="Search invoices" CLASS="fsblackbutton" onMouseOver="this.className='fsblackbuttonselected'; return true;" onMouseOut="this.className='fsblackbutton'; return true;" STYLE="font-size:70%">
             </FORM>
 % } 
-
         </TD>
 
         <TD COLSPAN=1 BGCOLOR="#000000" ALIGN="right">
index b0f657f..1ddafae 100755 (executable)
 %                            { 'address2' => { 'op'    => 'ILIKE',
 %                                              'value' => $address2 } } );
 %  push @cust_main, qsearch( 'cust_main',
-%                            { 'address2' => { 'op'    => 'ILIKE',
-%                                              'value' => $address2 } } )
-%    if defined dbdef->table('cust_main')->column('ship_last');
+%                            { 'ship_address2' => { 'op'    => 'ILIKE',
+%                                                   'value' => $address2 } } );
 %
 %  \@cust_main;
 %}
index 22594c5..20770e4 100644 (file)
   <TD ALIGN="right">Address</TD>
   <TD COLSPAN=7 BGCOLOR="#ffffff"><% $cust_main->get("${pre}address1") %></TD>
 </TR>
+
 % if ( $cust_main->get("${pre}address2") ) { 
+%   my $address2_label =
+%     ( $conf->exists('cust_main-require_address2')
+%       #  && (    ( !$which && !$cust_main->has_ship_address )
+%       #       || (  $which &&  $cust_main->has_ship_address )
+%       #     )
+%       && ! ( $which xor $cust_main->has_ship_address )
+%     )
+%       ? 'Unit&nbsp;#'
+%       : '&nbsp;';
+
+  <TR>
+    <TD ALIGN="right"><% $address2_label %></TD>
+    <TD COLSPAN=7 BGCOLOR="#ffffff"><% $cust_main->get("${pre}address2") %></TD>
+  </TR>
 
-<TR>
-  <TD ALIGN="right">&nbsp;</TD>
-  <TD COLSPAN=7 BGCOLOR="#ffffff"><% $cust_main->get("${pre}address2") %></TD>
-</TR>
 % } 
 
 <TR>