B<amount>: the amount to be paid; defaults to the customer's balance minus
any payments in transit.
-B<payby>: the payment method; defaults to cust_main.payby
-
B<realtime>: runs this as a realtime payment instead of adding it to a
batch. Deprecated.
the billing address for the payment; defaults to the customer's billing
location.
-B<payinfo>, B<paydate>, B<payname>: sets the payment account, expiration
-date, and name; defaults to those fields in cust_main.
+B<payby>, B<payinfo>, B<paydate>, B<payname>: sets the payment method,
+payment account, expiration date, and name; defaults to those fields
+in cust_main.
=cut
}else{
$amount = sprintf("%.2f", $self->balance - $self->in_transit_payments);
}
- return '' unless $amount > 0;
+ if ($amount <= 0) {
+ warn(sprintf("Customer balance %.2f - in transit amount %.2f is <= 0.\n",
+ $self->balance,
+ $self->in_transit_payments
+ ));
+ return;
+ }
my $invnum = delete $options{invnum};
- my $payby = $options{payby} || $self->payby; #still dubious
+
+ #pay fields should all come from either cust_payby or options, not both
+ # in theory, could just pass payby, and use it to select cust_payby,
+ # but nothing currently needs that, so not implementing it now
+ die "Incomplete payment details"
+ if ($options{payby} || $options{payinfo} || $options{paydate} || $options{payname})
+ && !($options{payby} && $options{payinfo} && $options{paydate} && $options{payname});
+
+ #false laziness with Billing_Realtime
+ my @cust_payby = $self->cust_payby('CARD','CHEK');
+
+ # batch can't try out every one like realtime, just use first one
+ my $cust_payby = $cust_payby[0];
+
+ die "No customer payment info found"
+ unless $options{payinfo} || $cust_payby;
+
+ my $payby = $options{payby} || $cust_payby->payby;
if ($options{'realtime'}) {
- return $self->realtime_bop( FS::payby->payby2bop($self->payby),
+ return $self->realtime_bop( FS::payby->payby2bop($payby),
$amount,
%options,
);
#this needs to handle mysql as well as Pg, like svc_acct.pm
#(make it into a common function if folks need to do batching with mysql)
$dbh->do("LOCK TABLE pay_batch IN SHARE ROW EXCLUSIVE MODE")
- or return "Cannot lock pay_batch: " . $dbh->errstr;
+ or die "Cannot lock pay_batch: " . $dbh->errstr;
my %pay_batch = (
'status' => 'O',
} );
foreach (qw( address1 address2 city state zip country latitude longitude
- payby payinfo paydate payname ))
+ payby payinfo paydate payname paycode ))
{
$options{$_} = '' unless exists($options{$_});
}
'state' => $options{state} || $loc->state,
'zip' => $options{zip} || $loc->zip,
'country' => $options{country} || $loc->country,
- 'payby' => $options{payby} || $self->payby,
- 'payinfo' => $options{payinfo} || $self->payinfo,
- 'exp' => $options{paydate} || $self->paydate,
- 'payname' => $options{payname} || $self->payname,
+ 'payby' => $options{payby} || $cust_payby->payby,
+ 'payinfo' => $options{payinfo} || $cust_payby->payinfo,
+ 'exp' => $options{paydate} || $cust_payby->paydate,
+ 'payname' => $options{payname} || $cust_payby->payname,
+ 'paytype' => $options{paytype} || $cust_payby->paytype,
'amount' => $amount, # consolidating
+ 'paycode' => $options{paycode} || $cust_payby->paycode,
} );
$cust_pay_batch->paybatchnum($old_cust_pay_batch->paybatchnum)
if ( $error ) {
$dbh->rollback if $oldAutoCommit;
- die $error;
+ #die $error;
+ return $error; # e.g. "Illegal zip" ala RT#75998
}
my $unapplied = $self->total_unapplied_credits
foreach my $cust_pay_batch ( qsearch('cust_pay_batch', {
'batchnum' => $pay_batch->batchnum,
'custnum' => $self->custnum,
+ 'status' => '',
} ) ) {
$in_transit_payments += $cust_pay_batch->amount;
}