use FS::UID qw( dbh driver_name );
use FS::Record qw( qsearchs qsearch dbdef regexp_sql );
use FS::Cursor;
-use FS::Misc qw( generate_ps do_print money_pretty );
+use FS::Misc qw( generate_ps do_print money_pretty card_types );
use FS::Msgcat qw(gettext);
use FS::CurrentUser;
use FS::TicketSystem;
$self->auto_agent_custid()
if $conf->config('cust_main-auto_agent_custid') && ! $self->agent_custid;
- my $error = $self->SUPER::insert;
+ my $error = $self->check_payinfo_cardtype
+ || $self->SUPER::insert;
if ( $error ) {
$dbh->rollback if $oldAutoCommit;
#return "inserting cust_main record (transaction rolled back): $error";
|| $old->payby =~ /^(CHEK|DCHK)$/ && $self->payby =~ /^(CHEK|DCHK)$/ )
&& ( $old->payinfo eq $self->payinfo || $old->paymask eq $self->paymask );
+ if ( $self->payby =~ /^(CARD|DCRD)$/
+ && $old->payinfo ne $self->payinfo
+ && $old->paymask ne $self->paymask )
+ {
+ my $error = $self->check_payinfo_cardtype;
+ return $error if $error;
+ }
+
return "Invoicing locale is required"
if $old->locale
&& ! $self->locale
$self->SUPER::check;
}
+sub check_payinfo_cardtype {
+ my $self = shift;
+
+ return '' unless $self->payby =~ /^(CARD|CHEK)$/;
+
+ my $payinfo = $self->payinfo;
+ $payinfo =~ s/\D//g;
+
+ return '' if $payinfo =~ /^99\d{14}$/; #token
+
+ my %bop_card_types = map { $_=>1 } values %{ card_types() };
+ my $cardtype = cardtype($payinfo);
+
+ return "$cardtype not accepted" unless $bop_card_types{$cardtype};
+
+ '';
+
+}
+
=item replace_check
Additional checks for replace only.
Saves a new cust_payby for this customer, replacing an existing entry only
in select circumstances. Does not validate input.
-If auto is specified, marks this as the customer's primary method (weight 1)
-and changes existing primary methods for that payby to secondary methods (weight 2.)
+If auto is specified, marks this as the customer's primary method, or the
+specified weight. Existing payment methods have their weight incremented as
+appropriate.
+
If bill_location is specified with auto, also sets location in cust_main.
Will not insert complete duplicates of existing records, or records in which the
Accepts the following named parameters:
-payment_payby - either CARD or CHEK
+=over 4
+
+=item payment_payby
-auto - save as an automatic payment type (CARD/CHEK if true, DCRD/DCHK if false)
+either CARD or CHEK
-payinfo - required
+=item auto
-paymask - optional, but should be specified for anything that might be tokenized, will be preserved when replacing
+save as an automatic payment type (CARD/CHEK if true, DCRD/DCHK if false)
-payname - required
+=item weight
-payip - optional, will be preserved when replacing
+optional, set higher than 1 for secondary, etc.
-paydate - CARD only, required
+=item payinfo
+
+required
-bill_location - CARD only, required, FS::cust_location object
+=item paymask
-paystart_month - CARD only, optional, will be preserved when replacing
+optional, but should be specified for anything that might be tokenized, will be preserved when replacing
-paystart_year - CARD only, optional, will be preserved when replacing
+=item payname
-payissue - CARD only, optional, will be preserved when replacing
+required
-paycvv - CARD only, only used if conf cvv-save is set appropriately
+=item payip
-paytype - CHEK only
+optional, will be preserved when replacing
-paystate - CHEK only
+=item paydate
+
+CARD only, required
+
+=item bill_location
+
+CARD only, required, FS::cust_location object
+
+=item paystart_month
+
+CARD only, optional, will be preserved when replacing
+
+=item paystart_year
+
+CARD only, optional, will be preserved when replacing
+
+=item payissue
+
+CARD only, optional, will be preserved when replacing
+
+=item paycvv
+
+CARD only, only used if conf cvv-save is set appropriately
+
+=item paytype
+
+CHEK only
+
+=item paystate
+
+CHEK only
+
+=back
=cut
#The code for this option is in place, but it's not currently used
#
-# replace - existing cust_payby object to be replaced (must match custnum)
+# =item replace
+#
+# existing cust_payby object to be replaced (must match custnum)
# stateid/stateid_state/ss are not currently supported in cust_payby,
# might not even work properly in 4.x, but will need to work here if ever added
@check_existing = qw( CHEK DCHK );
}
- # every automatic payment type added here will be marked primary
- $new->set( 'weight' => $opt{'auto'} ? 1 : '' );
+ $new->set( 'weight' => $opt{'auto'} ? $opt{'weight'} : '' );
# basic fields
$new->payinfo($opt{'payinfo'}); # sets default paymask, but not if it's already tokenized
# if we got this far, we're definitely replacing
$old = $cust_payby;
last PAYBYLOOP;
- }
+ } #PAYBYLOOP
}
if ($old) {
last unless $cust_payby->payby !~ /^D/;
last if $cust_payby->weight > 1;
next if $new->custpaybynum eq $cust_payby->custpaybynum;
- $cust_payby->set( 'weight' => 2 );
+ next if $cust_payby->weight < ($opt{'weight'} || 1);
+ $cust_payby->weight( $cust_payby->weight + 1 );
my $error = $cust_payby->replace;
if ( $error ) {
$dbh->rollback if $oldAutoCommit;