=item paybatchnum - primary key (automatically assigned)
-=item cardnum
+=item payinfo
=item exp - card expiration
my $error =
$self->ut_numbern('paybatchnum')
|| $self->ut_numbern('trancode') #depriciated
- || $self->ut_number('cardnum')
+ || $self->ut_number('payinfo')
|| $self->ut_money('amount')
|| $self->ut_number('invnum')
|| $self->ut_number('custnum')
$self->first =~ /^([\w \,\.\-\']+)$/ or return "Illegal first name";
$self->first($1);
- my $cardnum = $self->cardnum;
- $cardnum =~ s/\D//g;
- $cardnum =~ /^(\d{13,16})$/
- or return "Illegal credit card number";
- $cardnum = $1;
- $self->cardnum($cardnum);
- validate($cardnum) or return "Illegal credit card number";
- return "Unknown card type" if cardtype($cardnum) eq "Unknown";
+ # FIXME
+ # there is no point in false laziness here
+ # we will effectively set "check_payinfo to 0"
+ # we can change that when we finish the refactor
+
+ #my $cardnum = $self->cardnum;
+ #$cardnum =~ s/\D//g;
+ #$cardnum =~ /^(\d{13,16})$/
+ # or return "Illegal credit card number";
+ #$cardnum = $1;
+ #$self->cardnum($cardnum);
+ #validate($cardnum) or return "Illegal credit card number";
+ #return "Unknown card type" if cardtype($cardnum) eq "Unknown";
if ( $self->exp eq '' ) {
- return "Expriation date required"; #unless
+ return "Expiration date required"; #unless
$self->exp('');
} else {
if ( $self->exp =~ /^(\d{4})[\/\-](\d{1,2})[\/\-](\d{1,2})$/ ) {
$self->SUPER::check;
}
+=item cust_main
+
+Returns the customer (see L<FS::cust_main>) for this batched credit card
+payment.
+
+=cut
+
+sub cust_main {
+ my $self = shift;
+ qsearchs( 'cust_main', { 'custnum' => $self->custnum } );
+}
+
=back
=head1 SUBROUTINES
my $paybatch = $param->{'paybatch'};
my @fields;
- my $condition;
+ my $end_condition;
+ my $end_hook;
my $hook;
+ my $approved_condition;
+ my $declined_condition;
if ( $format eq 'csv-td_canada_trust-merchant_pc_batch' ) {
'', # Terminal ID: Terminal ID used to process the transaction
);
- $condition = sub {
+ $end_condition = sub {
my $hash = shift;
- $hash->{'result'} == 3 && $hash->{'type'} == 0;
+ $hash->{'type'} eq '0BC';
+ };
+
+ $end_hook = sub {
+ my( $hash, $total) = @_;
+ $total = sprintf("%.2f", $total);
+ my $batch_total = sprintf("%.2f", $hash->{'paybatchnum'} / 100 );
+ return "Our total $total does not match bank total $batch_total!"
+ if $total != $batch_total;
+ '';
};
$hook = sub {
substr($hash->{'_date'}, 0, 4)-1900, );
};
+ $approved_condition = sub {
+ my $hash = shift;
+ $hash->{'type'} eq '0' && $hash->{'result'} == 3;
+ };
+
+ $declined_condition = sub {
+ my $hash = shift;
+ $hash->{'type'} eq '0' && ( $hash->{'result'} == 4
+ || $hash->{'result'} == 5 );
+ };
+
+
} else {
return "Unknown format $format";
}
local $FS::UID::AutoCommit = 0;
my $dbh = dbh;
+ my $pay_batch = qsearchs('pay_batch',{'batchnum'=> $paybatch});
+ unless ($pay_batch && $pay_batch->status eq 'I') {
+ $dbh->rollback if $oldAutoCommit;
+ return "batch $paybatch is not in transit";
+ };
+
+ my %batchhash = $pay_batch->hash;
+ $batchhash{'status'} = 'R'; # Resolved
+ my $newbatch = new FS::pay_batch ( \%batchhash );
+ my $error = $newbatch->replace($paybatch);
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error
+ }
+
+ my $total = 0;
my $line;
while ( defined($line=<$fh>) ) {
+ next if $line =~ /^\s*$/; #skip blank lines
+
$csv->parse($line) or do {
$dbh->rollback if $oldAutoCommit;
return "can't parse: ". $csv->error_input();
$hash{$field} = $value;
}
+ if ( &{$end_condition}(\%hash) ) {
+ my $error = &{$end_hook}(\%hash, $total);
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
+ }
+ last;
+ }
+
my $cust_pay_batch =
qsearchs('cust_pay_batch', { 'paybatchnum' => $hash{'paybatchnum'} } );
unless ( $cust_pay_batch ) {
return "error removing paybatchnum $hash{'paybatchnum'}: $error\n";
}
- next unless &{$condition}(\%hash);
-
&{$hook}(\%hash);
- my $cust_pay = new FS::cust_pay ( {
- 'custnum' => $custnum,
- 'payby' => 'CARD',
- 'paybatch' => $paybatch,
- map { $_ => $hash{$_} } (qw( paid _date payinfo )),
- } );
- $error = $cust_pay->insert;
- if ( $error ) {
- $dbh->rollback if $oldAutoCommit;
- return "error adding payment paybatchnum $hash{'paybatchnum'}: $error\n";
- }
+ if ( &{$approved_condition}(\%hash) ) {
+
+ my $cust_pay = new FS::cust_pay ( {
+ 'custnum' => $custnum,
+ 'payby' => 'CARD',
+ 'paybatch' => $paybatch,
+ map { $_ => $hash{$_} } (qw( paid _date payinfo )),
+ } );
+ $error = $cust_pay->insert;
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return "error adding payment paybatchnum $hash{'paybatchnum'}: $error\n";
+ }
+ $total += $hash{'paid'};
+
+ $cust_pay->cust_main->apply_payments;
+
+ } elsif ( &{$declined_condition}(\%hash) ) {
- $cust_pay->cust_main->apply_payments;
+ #this should be configurable... if anybody else ever uses batches
+ $cust_pay_batch->cust_main->suspend;
+
+ }
}