use base qw( FS::cust_main::Packages
FS::cust_main::Billing FS::cust_main::Billing_Realtime
FS::otaker_Mixin FS::payinfo_Mixin FS::cust_main_Mixin
- FS::geocode_Mixin
FS::Record
);
use vars qw( $DEBUG $me $conf
use Digest::MD5 qw(md5_base64);
use Date::Format;
#use Date::Manip;
-use File::Temp; #qw( tempfile );
+use File::Temp qw( tempfile );
use Business::CreditCard 0.28;
use Locale::Country;
use FS::UID qw( getotaker dbh driver_name );
$self->payinfo($payinfo);
$self->paycvv('');
- unless ( $ignore_banned_card ) {
- my $ban = qsearchs('banned_pay', $self->_banned_pay_hashref);
- if ( $ban ) {
- return 'Banned ACH account: banned on '.
- time2str('%a %h %o at %r', $ban->_date).
- ' by '. $ban->otaker.
- ' (ban# '. $ban->bannum. ')';
- }
+ my $ban = qsearchs('banned_pay', $self->_banned_pay_hashref);
+ if ( $ban ) {
+ return 'Banned ACH account: banned on '.
+ time2str('%a %h %o at %r', $ban->_date).
+ ' by '. $ban->otaker.
+ ' (ban# '. $ban->bannum. ')';
}
} elsif ( $self->payby eq 'LECB' ) {
} else {
return "Illegal expiration date: ". $self->paydate;
}
- $m = sprintf('%02d',$m);
$self->paydate("$y-$m-01");
my($nowm,$nowy)=(localtime(time))[4,5]; $nowm++; $nowy+=1900;
return gettext('expired_card')
=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.
+city, county, state, zip, country. The shipping address is used if present.
=cut
+#geocode? dependent on tax-ship_address config, not available in cust_location
+#mostly. not yet then.
+
+sub location_hash {
+ my $self = shift;
+ my $prefix = $self->has_ship_address ? 'ship_' : '';
+
+ map { $_ => $self->get($prefix.$_) }
+ qw( address1 address2 city county state zip country geocode );
+ #fields that cust_location has
+}
+
=item cust_location
Returns all locations (see L<FS::cust_location>) for this customer.
qsearch('cust_location', { 'custnum' => $self->custnum } );
}
+=item location_label [ OPTION => VALUE ... ]
+
+Returns the label of the service location (see analog in L<FS::cust_location>) for this customer.
+
+Options are
+
+=over 4
+
+=item join_string
+
+used to separate the address elements (defaults to ', ')
+
+=item escape_function
+
+a callback used for escaping the text of the address elements
+
+=back
+
+=cut
+
+# false laziness with FS::cust_location::line
+
+sub location_label {
+ my $self = shift;
+ my %opt = @_;
+
+ my $separator = $opt{join_string} || ', ';
+ my $escape = $opt{escape_function} || sub{ shift };
+ my $line = '';
+ my $cydefault = FS::conf->new->config('countrydefault') || 'US';
+ my $prefix = length($self->ship_last) ? 'ship_' : '';
+
+ my $notfirst = 0;
+ foreach (qw ( address1 address2 ) ) {
+ my $method = "$prefix$_";
+ $line .= ($notfirst ? $separator : ''). &$escape($self->$method)
+ if $self->$method;
+ $notfirst++;
+ }
+ $notfirst = 0;
+ foreach (qw ( city county state zip ) ) {
+ my $method = "$prefix$_";
+ if ( $self->$method ) {
+ $line .= ' (' if $method eq 'county';
+ $line .= ($notfirst ? ' ' : $separator). &$escape($self->$method);
+ $line .= ' )' if $method eq 'county';
+ $notfirst++;
+ }
+ }
+ $line .= $separator. &$escape(code2country($self->country))
+ if $self->country ne $cydefault;
+
+ $line;
+}
+
=item unsuspend
Unsuspends all unflagged suspended packages (see L</unflagged_suspended_pkgs>
AND _date <= $time
";
- sprintf( "%.2f", $self->scalar_sql($sql) || 0 );
+ sprintf( "%.2f", $self->scalar_sql($sql) );
}
WHERE custnum = $custnum
";
- sprintf( "%.2f", $self->scalar_sql($sql) || 0 );
+ sprintf( "%.2f", $self->scalar_sql($sql) );
}
WHERE custnum = $custnum
";
- sprintf( "%.2f", $self->scalar_sql($sql) || 0 );
+ sprintf( "%.2f", $self->scalar_sql($sql) );
}
WHERE custnum = $custnum
";
- sprintf( "%.2f", $self->scalar_sql($sql) || 0 );
+ sprintf( "%.2f", $self->scalar_sql($sql) );
}
my $self = shift;
my $sql = 'SELECT SUM('. $self->balance_date_sql(@_).
') FROM cust_main WHERE custnum='. $self->custnum;
- sprintf( '%.2f', $self->scalar_sql($sql) || 0 );
+ sprintf( '%.2f', $self->scalar_sql($sql) );
}
=item balance_pkgnum PKGNUM
=cut
+sub geocode {
+ my ($self, $data_vendor) = (shift, shift); #always cch for now
+
+ my $geocode = $self->get('geocode'); #XXX only one data_vendor for geocode
+ return $geocode if $geocode;
+
+ my $prefix = ( $conf->exists('tax-ship_address') && length($self->ship_last) )
+ ? 'ship_'
+ : '';
+
+ my($zip,$plus4) = split /-/, $self->get("${prefix}zip")
+ if $self->country eq 'US';
+
+ $zip ||= '';
+ $plus4 ||= '';
+ #CCH specific location stuff
+ my $extra_sql = "AND plus4lo <= '$plus4' AND plus4hi >= '$plus4'";
+
+ my @cust_tax_location =
+ qsearch( {
+ 'table' => 'cust_tax_location',
+ 'hashref' => { 'zip' => $zip, 'data_vendor' => $data_vendor },
+ 'extra_sql' => $extra_sql,
+ 'order_by' => 'ORDER BY plus4hi',#overlapping with distinct ends
+ }
+ );
+ $geocode = $cust_tax_location[0]->geocode
+ if scalar(@cust_tax_location);
+
+ $geocode;
+}
+
=item cust_status
=item status
keys %statuscolor;
}
-=item cust_status_sql
-
-Returns an SQL fragment to determine the status of a cust_main record, as a
-string.
-
-=cut
-
-sub cust_status_sql {
- my $sql = 'CASE';
- for my $status ( FS::cust_main->statuses() ) {
- my $method = $status.'_sql';
- $sql .= ' WHEN ('.FS::cust_main->$method.") THEN '$status'";
- }
- $sql .= ' END';
- return $sql;
-}
-
-
=item prospect_sql
Returns an SQL expression identifying prospective cust_main records (customers
sub _upgrade_data { #class method
my ($class, %opts) = @_;
- my @statements = (
+ foreach my $sql (
'UPDATE h_cust_main SET paycvv = NULL WHERE paycvv IS NOT NULL',
- '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 ) {
- 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) = '-'";
- }
- else { # the SQL standard
- push @statements,
- "UPDATE cust_main SET paydate = SUBSTRING(paydate FROM 1 FOR 5) || '0' || SUBSTRING(paydate FROM 6) WHERE SUBSTRING(paydate FROM 7 FOR 1) = '-'";
- }
-
- foreach my $sql ( @statements ) {
+ 'UPDATE cust_main SET signupdate = (SELECT signupdate FROM h_cust_main WHERE h_cust_main.custnum = cust_main.custnum ORDER BY historynum ASC LIMIT 1) WHERE signupdate IS NULL',
+ ) {
my $sth = dbh->prepare($sql) or die dbh->errstr;
$sth->execute or die $sth->errstr;
}