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
$self->signupdate(time) unless $self->signupdate;
+ $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;
}
}
+ # 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;
}
- $self->set_coord
- if ! $self->coord_auto && ! $self->latitude && ! $self->longitude;
+ unless ( $import ) {
+ $self->set_coord
+ if ! $self->coord_auto && ! $self->latitude && ! $self->longitude;
- $self->set_coord('ship_')
- if $self->has_ship_address && ! $self->ship_coord_auto
- && ! $self->ship_latitude && ! $self->ship_longitude;
+ $self->set_coord('ship_')
+ if $self->has_ship_address && ! $self->ship_coord_auto
+ && ! $self->ship_latitude && ! $self->ship_longitude;
+ }
local($ignore_expired_card) = 1
if $old->payby =~ /^(CARD|DCRD)$/
|| $old->payby =~ /^(CHEK|DCHK)$/ && $self->payby =~ /^(CHEK|DCHK)$/ )
&& ( $old->payinfo eq $self->payinfo || $old->paymask eq $self->paymask );
+ if ( $self->censustract ne '' and $self->censustract ne $old->censustract ) {
+ # update censusyear whenever tract code changes
+ $self->censusyear($conf->config('census_year')||'2012');
+ }
+
+
local $SIG{HUP} = 'IGNORE';
local $SIG{INT} = 'IGNORE';
local $SIG{QUIT} = 'IGNORE';
}
}
+ # 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'} || [];
|| $self->ut_coordn('latitude')
|| $self->ut_coordn('longitude')
|| $self->ut_enum('coord_auto', [ '', 'Y' ])
+ || $self->ut_numbern('censusyear')
|| $self->ut_anything('comments')
|| $self->ut_numbern('referral_custnum')
|| $self->ut_textn('stateid')
|| $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')
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)
) {
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);
=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
}
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;
'';
sub display_custnum {
my $self = shift;
+ 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') ) {
+ $length = 8 if !defined($length);
return $conf->config('cust_main-custnum-display_prefix').
- sprintf('%08d', $self->custnum)
+ sprintf('%0'.$length.'d', $self->custnum)
+ } elsif ( $length ) {
+ return sprintf('%0'.$length.'d', $self->custnum);
} else {
return $self->custnum;
}
$cust_main->bill_and_collect( %$param );
}
+=item process_censustract_update CUSTNUM
+
+Queueable function to update the census tract to the current year (as set in
+the 'census_year' configuration variable) and retrieve the new tract code.
+
+=cut
+
+sub process_censustract_update {
+ eval "use FS::Misc::Geo qw(get_censustract)";
+ die $@ if $@;
+ my $custnum = shift;
+ my $cust_main = qsearchs( 'cust_main', { custnum => $custnum })
+ or die "custnum '$custnum' not found!\n";
+
+ my $new_year = $conf->config('census_year') or return;
+ my $new_tract = get_censustract({ $cust_main->location_hash }, $new_year);
+ if ( $new_tract =~ /^\d/ ) {
+ # 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;
+ }
+ else {
+ # it's an error message
+ die $new_tract;
+ }
+ return;
+}
+
sub _upgrade_data { #class method
my ($class, %opts) = @_;
'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) = '-'";
}
"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;
local($ignore_illegal_zip) = 1;
local($ignore_banned_card) = 1;
local($skip_fuzzyfiles) = 1;
+ local($import) = 1; #prevent automatic geocoding (need its own variable?)
$class->_upgrade_otaker(%opts);
}