add cust_main-require_locale configuration setting, RT#17594
[freeside.git] / FS / FS / cust_main.pm
index 687e311..cba28bc 100644 (file)
@@ -8,6 +8,7 @@ use base qw( FS::cust_main::Packages FS::cust_main::Status
              FS::cust_main::Billing_Discount
              FS::otaker_Mixin FS::payinfo_Mixin FS::cust_main_Mixin
              FS::geocode_Mixin
+             FS::o2m_Common
              FS::Record
            );
 use vars qw( $DEBUG $me $conf
@@ -465,7 +466,7 @@ sub insert {
 
   $self->signupdate(time) unless $self->signupdate;
 
-  $self->censusyear($conf->config('census_year')) if $self->censustract;
+  $self->censusyear($conf->config('census_year')||'2012') if $self->censustract;
 
   $self->auto_agent_custid()
     if $conf->config('cust_main-auto_agent_custid') && ! $self->agent_custid;
@@ -609,6 +610,20 @@ sub insert {
     }
   }
 
+  # FS::geocode_Mixin::after_insert or something?
+  if ( $conf->config('tax_district_method') and !$import ) {
+    # if anything non-empty, try to look it up
+    my $queue = new FS::queue {
+      'job'     => 'FS::geocode_Mixin::process_district_update',
+      'custnum' => $self->custnum,
+    };
+    my $error = $queue->insert( ref($self), $self->custnum );
+    if ( $error ) {
+      $dbh->rollback if $oldAutoCommit;
+      return "queueing tax district update: $error";
+    }
+  }
+
   # cust_main exports!
   warn "  exporting\n" if $DEBUG > 1;
 
@@ -1520,9 +1535,13 @@ sub replace {
 
   if ( $self->censustract ne '' and $self->censustract ne $old->censustract ) {
     # update censusyear whenever tract code changes
-    $self->censusyear($conf->config('census_year'));
+    $self->censusyear($conf->config('census_year')||'2012');
   }
 
+  return "Invoicing locale is required"
+    if $old->locale
+    && ! $self->locale
+    && $conf->exists('cust_main-require_locale');
 
   local $SIG{HUP} = 'IGNORE';
   local $SIG{INT} = 'IGNORE';
@@ -1633,6 +1652,25 @@ sub replace {
     }
   }
 
+  # FS::geocode_Mixin::after_replace ?
+  # though this will go away anyway once we move customer bill/service 
+  # locations into cust_location
+  # We can trigger this on any address change--just have to make sure 
+  # not to trigger it on itself.
+  if ( $conf->config('tax_district_method') and !$import 
+      and ( $self->get('ship_address1') ne $old->get('ship_address1')
+        or  $self->get('address1')      ne $old->get('address1') ) ) {
+    my $queue = new FS::queue {
+      'job'     => 'FS::geocode_Mixin::process_district_update',
+      'custnum' => $self->custnum,
+    };
+    my $error = $queue->insert( ref($self), $self->custnum );
+    if ( $error ) {
+      $dbh->rollback if $oldAutoCommit;
+      return "queueing tax district update: $error";
+    }
+  }
+
   # cust_main exports!
 
   my $export_args = $options{'export_args'} || [];
@@ -1739,6 +1777,7 @@ sub check {
     || $self->ut_textn('stateid_state')
     || $self->ut_textn('invoice_terms')
     || $self->ut_alphan('geocode')
+    || $self->ut_alphan('district')
     || $self->ut_floatn('cdr_termination_percentage')
     || $self->ut_floatn('credit_limit')
     || $self->ut_numbern('billday')
@@ -1813,7 +1852,7 @@ sub check {
     return $error if $error;
   }
 
-  if ( $conf->exists('cust_main-require_phone')
+  if ( $conf->exists('cust_main-require_phone', $self->agentnum)
        && ! length($self->daytime) && ! length($self->night) && ! length($self->mobile)
      ) {
 
@@ -1998,14 +2037,15 @@ sub check {
 
     my $payinfo = $self->payinfo;
     $payinfo =~ s/[^\d\@\.]//g;
-    if ( $conf->exists('cust_main-require-bank-branch') ) {
-      $payinfo =~ /^(\d+)\@(\d+)\.(\d+)$/ or return 'invalid echeck account@branch.bank';
+    if ( $conf->config('echeck-country') eq 'CA' ) {
+      $payinfo =~ /^(\d+)\@(\d{5})\.(\d{3})$/
+        or return 'invalid echeck account@branch.bank';
       $payinfo = "$1\@$2.$3";
-    } elsif ( $conf->exists('echeck-nonus') ) {
-      $payinfo =~ /^(\d+)\@(\d+)$/ or return 'invalid echeck account@aba';
+    } elsif ( $conf->config('echeck-country') eq 'US' ) {
+      $payinfo =~ /^(\d+)\@(\d{9})$/ or return 'invalid echeck account@aba';
       $payinfo = "$1\@$2";
     } else {
-      $payinfo =~ /^(\d+)\@(\d{9})$/ or return 'invalid echeck account@aba';
+      $payinfo =~ /^(\d+)\@(\d+)$/ or return 'invalid echeck account@routing';
       $payinfo = "$1\@$2";
     }
     $self->payinfo($payinfo);
@@ -2103,6 +2143,11 @@ sub check {
     $self->payname($1);
   }
 
+  return "Please select an invoicing locale"
+    if ! $self->locale
+    && ! $self->custnum
+    && $conf->exists('cust_main-require_locale');
+
   foreach my $flag (qw( tax spool_cdr squelch_cdr archived email_csv_cdr )) {
     $self->$flag() =~ /^(Y?)$/ or return "Illegal $flag: ". $self->$flag();
     $self->$flag($1);
@@ -2143,8 +2188,9 @@ sub has_ship_address {
 
 =item location_hash
 
-Returns a list of key/value pairs, with the following keys: address1, adddress2,
-city, county, state, zip, country, and geocode.  The shipping address is used if present.
+Returns a list of key/value pairs, with the following keys: address1, 
+adddress2, city, county, state, zip, country, district, and geocode.  The 
+shipping address is used if present.
 
 =cut
 
@@ -3178,7 +3224,7 @@ sub check_invoicing_list {
   }
 
   return "Email address required"
-    if $conf->exists('cust_main-require_invoicing_list_email')
+    if $conf->exists('cust_main-require_invoicing_list_email', $self->agentnum)
     && ! grep { $_ !~ /^([A-Z]+)$/ } @$arrayref;
 
   '';
@@ -3925,11 +3971,35 @@ 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', $self->agentnum) || '';
+  if ( my $special = $conf->config('cust_main-custnum-display_special') ) {
+    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 =~ /^(..)/),
+        ($self->classnum ? $self->cust_class->classname =~ /^(..)/ : '__')
+      ) );
+    }
+    # add any others here if needed
+  }
+
+  my $length = $conf->config('cust_main-custnum-display_length');
   if ( $conf->exists('cust_main-default_agent_custid') && $self->agent_custid ){
     return $self->agent_custid;
-  } elsif ( $conf->config('cust_main-custnum-display_prefix') ) {
-    return $conf->config('cust_main-custnum-display_prefix').
-           sprintf('%08d', $self->custnum)
+  } elsif ( $prefix ) {
+    $length = 8 if !defined($length);
+    return $prefix . 
+           sprintf('%0'.$length.'d', $self->custnum)
+  } elsif ( $length ) {
+    return sprintf('%0'.$length.'d', $self->custnum);
   } else {
     return $self->custnum;
   }
@@ -5000,6 +5070,12 @@ sub process_censustract_update {
     # then it's a tract code
         $cust_main->set('censustract', $new_tract);
     $cust_main->set('censusyear',  $new_year);
+
+    local($ignore_expired_card) = 1;
+    local($ignore_illegal_zip) = 1;
+    local($ignore_banned_card) = 1;
+    local($skip_fuzzyfiles) = 1;
+    local($import) = 1; #prevent automatic geocoding (need its own variable?)
     my $error = $cust_main->replace;
     die $error if $error;
   }
@@ -5018,7 +5094,7 @@ sub _upgrade_data { #class method
     'UPDATE cust_main SET signupdate = (SELECT signupdate FROM h_cust_main WHERE signupdate IS NOT NULL AND h_cust_main.custnum = cust_main.custnum ORDER BY historynum DESC LIMIT 1) WHERE signupdate IS NULL',
   );
   # fix yyyy-m-dd formatted paydates
-  if ( driver_name =~ /^mysql$/i ) {
+  if ( driver_name =~ /^mysql/i ) {
     push @statements,
     "UPDATE cust_main SET paydate = CONCAT( SUBSTRING(paydate FROM 1 FOR 5), '0', SUBSTRING(paydate FROM 6) ) WHERE SUBSTRING(paydate FROM 7 FOR 1) = '-'";
   }
@@ -5027,6 +5103,10 @@ sub _upgrade_data { #class method
     "UPDATE cust_main SET paydate = SUBSTRING(paydate FROM 1 FOR 5) || '0' || SUBSTRING(paydate FROM 6) WHERE SUBSTRING(paydate FROM 7 FOR 1) = '-'";
   }
 
+  push @statements, #fix the weird BILL with a cc# in payinfo problem
+    #DCRD to be safe
+    "UPDATE cust_main SET payby = 'DCRD' WHERE payby = 'BILL' and length(payinfo) = 16 and payinfo ". regexp_sql. q( '^[0-9]*$' );
+
   foreach my $sql ( @statements ) {
     my $sth = dbh->prepare($sql) or die dbh->errstr;
     $sth->execute or die $sth->errstr;