use FS::cust_main_note;
use FS::cust_attachment;
use FS::contact;
+use FS::Locales;
# 1 is mostly method/subroutine entry and options
# 2 traces progress of some operations
&& $self->payby =~ /^(CARD|DCRD)$/
&& ( $old->payinfo eq $self->payinfo || $old->paymask eq $self->paymask );
+ local($ignore_banned_card) = 1
+ if ( $old->payby =~ /^(CARD|DCRD)$/ && $self->payby =~ /^(CARD|DCRD)$/
+ || $old->payby =~ /^(CHEK|DCHK)$/ && $self->payby =~ /^(CHEK|DCHK)$/ )
+ && ( $old->payinfo eq $self->payinfo || $old->paymask eq $self->paymask );
+
local $SIG{HUP} = 'IGNORE';
local $SIG{INT} = 'IGNORE';
local $SIG{QUIT} = 'IGNORE';
|| $self->ut_floatn('credit_limit')
|| $self->ut_numbern('billday')
|| $self->ut_enum('edit_subject', [ '', 'Y' ] )
+ || $self->ut_enum('locale', [ '', FS::Locales->locales ])
;
#barf. need message catalogs. i18n. etc.
if ( $ban ) {
if ( $ban->bantype eq 'warn' ) {
#or others depending on value of $ban->reason ?
- return '_duplicate_card' unless $self->override_ban_warn;
+ return '_duplicate_card'.
+ ': disabled from'. time2str('%a %h %o at %r', $ban->_date).
+ ' until '. time2str('%a %h %o at %r', $ban->_end_date).
+ ' (ban# '. $ban->bannum. ')'
+ unless $self->override_ban_warn;
} else {
return 'Banned credit card: banned on '.
time2str('%a %h %o at %r', $ban->_date).
if ( $conf->exists('cust_main-require-bank-branch') ) {
$payinfo =~ /^(\d+)\@(\d+)\.(\d+)$/ or return 'invalid echeck account@branch.bank';
$payinfo = "$1\@$2.$3";
- }
- elsif ( $conf->exists('echeck-nonus') ) {
+ } elsif ( $conf->exists('echeck-no_routing') ) {
+ $payinfo =~ /^(\d+)\@(\d*)$/ or return 'invalid echeck account';
+ $payinfo = "$1\@$2";
+ } elsif ( $conf->exists('echeck-nonus') ) {
$payinfo =~ /^(\d+)\@(\d+)$/ or return 'invalid echeck account@aba';
$payinfo = "$1\@$2";
} else {
qsearch($opt);
}
+=item svc_x SVCDB [ OPTION => VALUE | EXTRA_QSEARCH_PARAMS_HASHREF ]
+
+Returns all services of type SVCDB (such as 'svc_acct') for this customer.
+
+Optionally, a list or hashref of additional arguments to the qsearch call can
+be passed following the SVCDB.
+
+=cut
+
+sub svc_x {
+ my $self = shift;
+ my $svcdb = shift;
+ if ( ! $svcdb =~ /^svc_\w+$/ ) {
+ warn "$me svc_x requires a svcdb";
+ return;
+ }
+ my $opt = ref($_[0]) ? shift : { @_ };
+
+ $opt->{'table'} = $svcdb;
+ $opt->{'addl_from'} =
+ 'LEFT JOIN cust_svc USING (svcnum) LEFT JOIN cust_pkg USING (pkgnum) '.
+ ($opt->{'addl_from'} || '');
+
+ my $custnum = $self->custnum;
+ $custnum =~ /^\d+$/ or die "bad custnum '$custnum'";
+ my $where = "cust_pkg.custnum = $custnum";
+
+ my $extra_sql = $opt->{'extra_sql'} || '';
+ if ( keys %{ $opt->{'hashref'} } ) {
+ $extra_sql = " AND $where $extra_sql";
+ }
+ else {
+ if ( $opt->{'extra_sql'} =~ /^\s*where\s(.*)/si ) {
+ $extra_sql = "WHERE $where AND $1";
+ }
+ else {
+ $extra_sql = "WHERE $where $extra_sql";
+ }
+ }
+ $opt->{'extra_sql'} = $extra_sql;
+
+ qsearch($opt);
+}
+
+# required for use as an eventtable;
+sub svc_acct {
+ my $self = shift;
+ $self->svc_x('svc_acct', @_);
+}
+
=item cust_credit
Returns all the credits (see L<FS::cust_credit>) for this customer.