package FS::pay_batch;
+use base qw( FS::Record );
use strict;
-use vars qw( @ISA $DEBUG %import_info %export_info $conf );
+use vars qw( $DEBUG %import_info %export_info $conf );
+use Scalar::Util qw(blessed);
+use IO::Scalar;
+use List::Util qw(sum);
use Time::Local;
use Text::CSV_XS;
-use FS::Record qw( dbh qsearch qsearchs );
-use FS::Conf;
-use FS::cust_pay;
-use FS::agent;
use Date::Parse qw(str2time);
use Business::CreditCard qw(cardtype);
-use Scalar::Util 'blessed';
-use IO::Scalar;
use FS::Misc qw(send_email); # for error notification
-use List::Util qw(sum);
-
-@ISA = qw(FS::Record);
+use FS::Record qw( dbh qsearch qsearchs );
+use FS::Conf;
+use FS::cust_pay;
=head1 NAME
Returns the L<FS::agent> object for this batch.
-=cut
-
-sub agent {
- qsearchs('agent', { 'agentnum' => $_[0]->agentnum });
-}
-
=item cust_pay_batch
Returns all L<FS::cust_pay_batch> objects for this batch.
-=cut
-
-sub cust_pay_batch {
- qsearch('cust_pay_batch', { 'batchnum' => $_[0]->batchnum });
-}
-
=item rebalance
=cut
\\%FS::pay_batch::$mod\::export_info,
\$FS::pay_batch::$mod\::name)";
$name ||= $mod; # in case it's not defined
- if( $@) {
+ if ($@) {
# in FS::cdr this is a die, not a warn. That's probably a bug.
warn "error using FS::pay_batch::$mod (skipping): $@\n";
next;
I<gateway> - an L<FS::payment_gateway> object for a batch gateway. This
takes precedence over I<format>.
+Supported format keys (defined in the specified FS::pay_batch module) are:
+
+I<filetype> - required, can be CSV, fixed, variable, XML
+
+I<fields> - required list of field names for each row/line
+
+I<formatre> - regular expression for fixed filetype
+
+I<parse> - required for variable filetype
+
+I<xmlkeys> - required for XML filetype
+
+I<xmlrow> - required for XML filetype
+
+I<begin_condition> - sub, ignore all lines before this returns true
+
+I<end_condition> - sub, stop processing lines when this returns true
+
+I<end_hook> - sub, runs immediately after end_condition returns true
+
+I<skip_condition> - sub, skip lines when this returns true
+
+I<hook> - required, sub, runs before approved/declined conditions are checked
+
+I<approved> - required, sub, returns true when approved
+
+I<declined> - required, sub, returns true when declined
+
+I<close_condition> - sub, decide whether or not to close the batch
+
=cut
sub import_results {
foreach ('paid', '_date', 'payinfo') {
$new_cust_pay_batch->$_($hash{$_}) if $hash{$_};
}
- $error = $new_cust_pay_batch->approve($hash{'paybatch'} || $self->batchnum);
+ $error = $new_cust_pay_batch->approve(%hash);
$total += $hash{'paid'};
} elsif ( &{$declined_condition}(\%hash) ) {
- $error = $new_cust_pay_batch->decline;
+ $error = $new_cust_pay_batch->decline($hash{'error_message'});;
}
}
-use MIME::Base64;
-use Storable 'thaw';
use Data::Dumper;
sub process_import_results {
my $job = shift;
- my $param = thaw(decode_base64(shift));
+ my $param = shift;
$param->{'job'} = $job;
warn Dumper($param) if $DEBUG;
my $gatewaynum = delete $param->{'gatewaynum'};
my $processor = $gateway->batch_processor(%proc_opt);
- my @batches = $processor->receive;
+ my @processor_ids = map { $_->processor_id }
+ qsearch({
+ 'table' => 'pay_batch',
+ 'hashref' => { 'status' => 'I' },
+ 'extra_sql' => q( AND processor_id != '' AND processor_id IS NOT NULL)
+ });
+
+ my @batches = $processor->receive(@processor_ids);
my $num = 0;
my $payby; # CARD or CHEK
my $error;
- # follow realtime gateway practice here
- # though eventually this stuff should go into separate fields...
my $paybatch = $gateway->gatewaynum . '-' . $gateway->gateway_module .
':' . $item->authorization . ':' . $item->order_number;
payby => $payby,
invnum => $item->invoice_number,
batchnum => $pay_batch->batchnum,
- paybatch => $paybatch,
payinfo => $payinfo,
+ gatewaynum => $gateway->gatewaynum,
+ processor => $gateway->gateway_module,
+ auth => $item->authorization,
+ order_number => $item->order_number,
}
);
$error ||= $cust_pay->insert;
# approval status
if ( $item->approved ) {
# follow Billing_Realtime format for paybatch
- $error = $cust_pay_batch->approve($paybatch);
+ $error = $cust_pay_batch->approve(
+ 'gatewaynum' => $gateway->gatewaynum,
+ 'processor' => $gateway->gateway_module,
+ 'auth' => $item->authorization,
+ 'order_number' => $item->order_number,
+ );
$total += $cust_pay_batch->paid;
}
else {
- $error = $cust_pay_batch->decline($item->error_message);
+ $error = $cust_pay_batch->decline($item->error_message,
+ $item->failure_status);
}
if ( $error ) {
my $body = "Import from gateway ".$gateway->label."\n".$error_text;
send_email(
to => $mail_on_error,
- from => $conf->config('invoice_from'),
+ from => $conf->invoice_from_full(),
subject => $subject,
body => $body,
);
}
return $error if $error;
}
+ } elsif ( @unresolved ) {
+ # auto resolve is not enabled, and we're not ready to resolve
+ return;
}
$self->set_status('R');
my $info = $export_info{$format} or die "Format not found: '$format'\n";
- &{$info->{'init'}}($conf) if exists($info->{'init'});
+ &{$info->{'init'}}($conf, $self->agentnum) if exists($info->{'init'});
my $oldAutoCommit = $FS::UID::AutoCommit;
local $FS::UID::AutoCommit = 0;
);
$processor->submit($batch);
+ if ($batch->processor_id) {
+ $self->set('processor_id',$batch->processor_id);
+ $self->replace;
+ }
+
$dbh->commit or die $dbh->errstr if $oldAutoCommit;
'';
}
my $self = shift;
my $date = time;
my %opt = @_;
- my $paybatch = $opt{'paybatch'} || $self->batchnum;
my $usernum = $opt{'usernum'} || die "manual approval requires a usernum";
my $conf = FS::Conf->new;
return 'manual batch approval disabled'
'_date' => $date,
'usernum' => $usernum,
};
- my $error = $new_cust_pay_batch->approve($paybatch);
+ my $error = $new_cust_pay_batch->approve();
+ # there are no approval options here (authorization, order_number, etc.)
+ # because the transaction wasn't really approved
if ( $error ) {
$dbh->rollback;
return 'paybatchnum '.$cust_pay_batch->paybatchnum.": $error";
for my $format (keys %export_info) {
my $mod = "FS::pay_batch::$format";
if ( $mod->can('_upgrade_gateway')
- and exists( $conf->config("batchconfig-$format") ) ) {
+ and $conf->exists("batchconfig-$format") ) {
local $@;
my ($module, %gw_options) = $mod->_upgrade_gateway;