[freeside-commits] freeside/FS/FS Schema.pm, 1.19, 1.20 Setup.pm,
1.3, 1.4 cust_bill.pm, 1.149, 1.150 cust_main.pm, 1.220,
1.221 cust_pay_batch.pm, 1.12, 1.13 part_bill_event.pm, 1.22,
1.23 pay_batch.pm, 1.2, 1.3 payby.pm, 1.3, 1.4
Jeff Finucane,420,,
jeff at wavetail.420.am
Tue Aug 8 23:43:03 PDT 2006
Update of /home/cvs/cvsroot/freeside/FS/FS
In directory wavetail:/tmp/cvs-serv27643/FS/FS
Modified Files:
Schema.pm Setup.pm cust_bill.pm cust_main.pm cust_pay_batch.pm
part_bill_event.pm pay_batch.pm payby.pm
Log Message:
batch refactor
Index: part_bill_event.pm
===================================================================
RCS file: /home/cvs/cvsroot/freeside/FS/FS/part_bill_event.pm,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -d -r1.22 -r1.23
--- part_bill_event.pm 18 Feb 2006 02:11:44 -0000 1.22
+++ part_bill_event.pm 9 Aug 2006 06:43:01 -0000 1.23
@@ -144,7 +144,7 @@
}
my $error = $self->ut_numbern('eventpart')
- || $self->ut_enum('payby', [qw( CARD DCRD CHEK DCHK LECB BILL COMP )] )
+ || $self->ut_enum('payby', [qw( CARD DCLN DCRD CHEK DCHK LECB BILL COMP )] )
|| $self->ut_text('event')
|| $self->ut_anything('eventcode')
|| $self->ut_number('seconds')
Index: payby.pm
===================================================================
RCS file: /home/cvs/cvsroot/freeside/FS/FS/payby.pm,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- payby.pm 14 May 2006 16:47:31 -0000 1.3
+++ payby.pm 9 Aug 2006 06:43:01 -0000 1.4
@@ -90,6 +90,11 @@
shortname => 'Complimentary',
longname => 'Complimentary',
},
+ 'DCLN' => { # This is only an event.
+ tinyname => 'declined',
+ shortname => 'Declined payment',
+ longname => 'Declined payment',
+ },
;
sub payby {
Index: cust_main.pm
===================================================================
RCS file: /home/cvs/cvsroot/freeside/FS/FS/cust_main.pm,v
retrieving revision 1.220
retrieving revision 1.221
diff -u -d -r1.220 -r1.221
--- cust_main.pm 24 Jul 2006 22:40:37 -0000 1.220
+++ cust_main.pm 9 Aug 2006 06:43:01 -0000 1.221
@@ -2046,6 +2046,8 @@
freq - "1d" for the traditional, daily events (the default), or "1m" for the
new monthly events
+payby - allows for one time override of normal customer billing method
+
=cut
sub collect {
@@ -2116,7 +2118,10 @@
}
qsearch( {
'table' => 'part_bill_event',
- 'hashref' => { 'payby' => $self->payby,
+ 'hashref' => { 'payby' => (exists($options{'payby'})
+ ? $options{'payby'}
+ : $self->payby
+ ),
'disabled' => '', },
'extra_sql' => $extra_sql,
} )
@@ -3143,6 +3148,29 @@
);
}
+=item in_transit_payments
+
+Returns the total of requests for payments for this customer pending in
+batches in transit to the bank. See L<FS::pay_batch> and L<FS::cust_pay_batch>
+
+=cut
+
+sub in_transit_payments {
+ my $self = shift;
+ my $in_transit_payments = 0;
+ foreach my $pay_batch ( qsearch('pay_batch', {
+ 'status' => 'I',
+ } ) ) {
+ foreach my $cust_pay_batch ( qsearch('cust_pay_batch', {
+ 'batchnum' => $pay_batch->batchnum,
+ 'custnum' => $self->custnum,
+ } ) ) {
+ $in_transit_payments += $cust_pay_batch->amount;
+ }
+ }
+ sprintf( "%.2f", $in_transit_payments );
+}
+
=item paydate_monthyear
Returns a two-element list consisting of the month and year of this customer's
Index: Setup.pm
===================================================================
RCS file: /home/cvs/cvsroot/freeside/FS/FS/Setup.pm,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- Setup.pm 14 Jul 2006 00:42:56 -0000 1.3
+++ Setup.pm 9 Aug 2006 06:43:01 -0000 1.4
@@ -168,6 +168,13 @@
'weight' => 50,
'plan' => 'send',
},
+ { 'payby' => 'DCLN',
+ 'event' => 'Suspend',
+ 'seconds' => 0,
+ 'eventcode' => '$cust_bill->suspend();',
+ 'weight' => 40,
+ 'plan' => 'suspend',
+ },
],
#you must create a service definition. An example of a service definition
Index: pay_batch.pm
===================================================================
RCS file: /home/cvs/cvsroot/freeside/FS/FS/pay_batch.pm,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- pay_batch.pm 16 Jun 2006 01:23:40 -0000 1.2
+++ pay_batch.pm 9 Aug 2006 06:43:01 -0000 1.3
@@ -34,7 +34,11 @@
=item batchnum - primary key
-=item status -
+=item status -
+
+=item download -
+
+=item upload -
=back
@@ -109,7 +113,7 @@
=head1 BUGS
-The author forgot to customize this manpage.
+status is somewhat redundant now that download and upload exist
=head1 SEE ALSO
Index: cust_bill.pm
===================================================================
RCS file: /home/cvs/cvsroot/freeside/FS/FS/cust_bill.pm,v
retrieving revision 1.149
retrieving revision 1.150
diff -u -d -r1.149 -r1.150
--- cust_bill.pm 16 Jul 2006 00:55:05 -0000 1.149
+++ cust_bill.pm 9 Aug 2006 06:43:01 -0000 1.150
@@ -1284,6 +1284,9 @@
my $self = shift;
my $cust_main = $self->cust_main;
+ my $amount = sprintf("%.2f", $cust_main->balance - $cust_main->in_transit_payments);
+ return '' unless $amount > 0;
+
my $oldAutoCommit = $FS::UID::AutoCommit;
local $FS::UID::AutoCommit = 0;
my $dbh = dbh;
@@ -1300,9 +1303,14 @@
}
}
+ my $old_cust_pay_batch = qsearchs('cust_pay_batch', {
+ 'batchnum' => $pay_batch->getfield('batchnum'),
+ 'custnum' => $cust_main->getfield('custnum'),
+ } );
+
my $cust_pay_batch = new FS::cust_pay_batch ( {
'batchnum' => $pay_batch->getfield('batchnum'),
- 'invnum' => $self->getfield('invnum'),
+ 'invnum' => $self->getfield('invnum'), # is there a better value?
'custnum' => $cust_main->getfield('custnum'),
'last' => $cust_main->getfield('last'),
'first' => $cust_main->getfield('first'),
@@ -1312,12 +1320,23 @@
'state' => $cust_main->getfield('state'),
'zip' => $cust_main->getfield('zip'),
'country' => $cust_main->getfield('country'),
+ 'payby' => $cust_main->payby,
'payinfo' => $cust_main->payinfo,
'exp' => $cust_main->getfield('paydate'),
'payname' => $cust_main->getfield('payname'),
- 'amount' => $self->owed,
+ 'amount' => $amount, # consolidating
} );
- my $error = $cust_pay_batch->insert;
+
+ $cust_pay_batch->paybatchnum($old_cust_pay_batch->paybatchnum)
+ if $old_cust_pay_batch;
+
+ my $error;
+ if ($old_cust_pay_batch) {
+ $error = $cust_pay_batch->replace($old_cust_pay_batch)
+ } else {
+ $error = $cust_pay_batch->insert;
+ }
+
if ( $error ) {
$dbh->rollback if $oldAutoCommit;
die $error;
Index: Schema.pm
===================================================================
RCS file: /home/cvs/cvsroot/freeside/FS/FS/Schema.pm,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -d -r1.19 -r1.20
--- Schema.pm 7 Aug 2006 02:44:28 -0000 1.19
+++ Schema.pm 9 Aug 2006 06:43:01 -0000 1.20
@@ -542,7 +542,9 @@
'pay_batch' => { #batches of payments to an external processor
'columns' => [
'batchnum', 'serial', '', '', '', '',
- 'status', 'char', 'NULL', 1, '', '',
+ 'status', 'char', 'NULL', 1, '', '',
+ 'download', @date_type, 'NULL', '',
+ 'upload', @date_type, 'NULL', '',
],
'primary_key' => 'batchnum',
'unique' => [],
@@ -565,11 +567,13 @@
'zip', 'varchar', 'NULL', 10, '', '',
'country', 'char', '', 2, '', '',
# 'trancode', 'int', '', '', '', ''
+ 'payby', 'char', '', 4, '', '', # CARD/BILL/COMP, should be
'payinfo', 'varchar', '', 512, '', '',
#'exp', @date_type, '', ''
- 'exp', 'varchar', '', 11, '', '',
+ 'exp', 'varchar', 'NULL', 11, '', '',
'payname', 'varchar', 'NULL', $char_d, '', '',
'amount', @money_type, '', '',
+ 'status', 'varchar', 'NULL', $char_d, '', '',
],
'primary_key' => 'paybatchnum',
'unique' => [],
Index: cust_pay_batch.pm
===================================================================
RCS file: /home/cvs/cvsroot/freeside/FS/FS/cust_pay_batch.pm,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -d -r1.12 -r1.13
--- cust_pay_batch.pm 20 May 2006 20:06:30 -0000 1.12
+++ cust_pay_batch.pm 9 Aug 2006 06:43:01 -0000 1.13
@@ -1,12 +1,17 @@
package FS::cust_pay_batch;
use strict;
-use vars qw( @ISA );
-use FS::Record qw(dbh qsearchs);
+use vars qw( @ISA $DEBUG );
+use FS::Record qw(dbh qsearch qsearchs);
use Business::CreditCard;
@ISA = qw( FS::Record );
+# 1 is mostly method/subroutine entry and options
+# 2 traces progress of some operations
+# 3 is even more information including possibly sensitive data
+$DEBUG = 0;
+
=head1 NAME
FS::cust_pay_batch - Object methods for batch cards
@@ -37,6 +42,10 @@
=item paybatchnum - primary key (automatically assigned)
+=item batchnum - indentifies group in batch
+
+=item payby - CARD/CHEK/LECB/BILL/COMP
+
=item payinfo
=item exp - card expiration
@@ -65,6 +74,8 @@
=item country
+=item status
+
=back
=head1 METHODS
@@ -94,16 +105,8 @@
=item replace OLD_RECORD
-#inactive
-#
-#Replaces the OLD_RECORD with this one in the database. If there is an error,
-#returns the error, otherwise returns false.
-
-=cut
-
-sub replace {
- return "Can't (yet?) replace batched transactions!";
-}
+Replaces the OLD_RECORD with this one in the database. If there is an error,
+returns the error, otherwise returns false.
=item check
@@ -119,7 +122,6 @@
my $error =
$self->ut_numbern('paybatchnum')
|| $self->ut_numbern('trancode') #depriciated
- || $self->ut_number('payinfo')
|| $self->ut_money('amount')
|| $self->ut_number('invnum')
|| $self->ut_number('custnum')
@@ -137,6 +139,10 @@
$self->first =~ /^([\w \,\.\-\']+)$/ or return "Illegal first name";
$self->first($1);
+ $self->payby =~ /^(CARD|CHEK|LECB|BILL|COMP|PREP|CASH|WEST|MCRD)$/
+ or return "Illegal payby";
+ $self->payby($1);
+
# FIXME
# there is no point in false laziness here
# we will effectively set "check_payinfo to 0"
@@ -152,7 +158,8 @@
#return "Unknown card type" if cardtype($cardnum) eq "Unknown";
if ( $self->exp eq '' ) {
- return "Expiration date required"; #unless
+ return "Expiration date required"
+ unless $self->payby =~ /^(CHEK|DCHK|LECB|WEST)$/;
$self->exp('');
} else {
if ( $self->exp =~ /^(\d{4})[\/\-](\d{1,2})[\/\-](\d{1,2})$/ ) {
@@ -226,7 +233,11 @@
my $format = $param->{'format'};
my $paybatch = $param->{'paybatch'};
+ my $filetype; # CSV, Fixed80, Fixed264
my @fields;
+ my $formatre; # for Fixed.+
+ my @values;
+ my $begin_condition;
my $end_condition;
my $end_hook;
my $hook;
@@ -235,6 +246,8 @@
if ( $format eq 'csv-td_canada_trust-merchant_pc_batch' ) {
+ $filetype = "CSV";
+
@fields = (
'paybatchnum', # Reference#: Invoice number of the transaction
'paid', # Amount: Amount of the transaction. Dollars and cents
@@ -293,6 +306,58 @@
};
+ }elsif ( $format eq 'PAP' ) {
+
+ $filetype = "Fixed264";
+
+ @fields = (
+ 'recordtype', # We are interested in the 'D' or debit records
+ 'batchnum', # Record#: batch number we used when sending the file
+ 'datacenter', # Where in the bowels of the bank the data was processed
+ 'paid', # Amount: Amount of the transaction. Dollars and cents
+ # with no decimal entered.
+ '_date', # Transaction Date: Date the Transaction was processed
+ 'bank', # Routing information
+ 'payinfo', # Account number for the transaction
+ 'paybatchnum', # Reference#: Invoice number of the transaction
+ );
+
+ $formatre = '^(.).{19}(.{4})(.{3})(.{10})(.{6})(.{9})(.{12}).{110}(.{19}).{71}$';
+
+ $end_condition = sub {
+ my $hash = shift;
+ $hash->{'recordtype'} eq 'W';
+ };
+
+ $end_hook = sub {
+ my( $hash, $total) = @_;
+ $total = sprintf("%.2f", $total);
+ my $batch_total = $hash->{'datacenter'}.$hash->{'paid'}.
+ substr($hash->{'_date'},0,1); # YUCK!
+ $batch_total = sprintf("%.2f", $batch_total / 100 );
+ return "Our total $total does not match bank total $batch_total!"
+ if $total != $batch_total;
+ '';
+ };
+
+ $hook = sub {
+ my $hash = shift;
+ $hash->{'paid'} = sprintf("%.2f", $hash->{'paid'} / 100 );
+ my $tmpdate = timelocal( 0,0,1,1,0,substr($hash->{'_date'}, 0, 3)+2000);
+ $tmpdate += 86400*(substr($hash->{'_date'}, 3, 3)-1) ;
+ $hash->{'_date'} = $tmpdate;
+ $hash->{'payinfo'} = $hash->{'payinfo'} . '@' . $hash->{'bank'};
+ };
+
+ $approved_condition = sub {
+ 1;
+ };
+
+ $declined_condition = sub {
+ 0;
+ };
+
+
} else {
return "Unknown format $format";
}
@@ -316,10 +381,10 @@
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);
+ my $newbatch = new FS::pay_batch { $pay_batch->hash };
+ $newbatch->status('R'); # Resolved
+ $newbatch->upload(time);
+ my $error = $newbatch->replace($pay_batch);
if ( $error ) {
$dbh->rollback if $oldAutoCommit;
return $error
@@ -331,12 +396,23 @@
next if $line =~ /^\s*$/; #skip blank lines
- $csv->parse($line) or do {
+ if ($filetype eq "CSV") {
+ $csv->parse($line) or do {
+ $dbh->rollback if $oldAutoCommit;
+ return "can't parse: ". $csv->error_input();
+ };
+ @values = $csv->fields();
+ }elsif ($filetype eq "Fixed80" || $filetype eq "Fixed264"){
+ @values = $line =~ /$formatre/;
+ unless (@values) {
+ $dbh->rollback if $oldAutoCommit;
+ return "can't parse: ". $line;
+ };
+ }else{
$dbh->rollback if $oldAutoCommit;
- return "can't parse: ". $csv->error_input();
- };
+ return "Unknown file type $filetype";
+ }
- my @values = $csv->fields();
my %hash;
foreach my $field ( @fields ) {
my $value = shift @values;
@@ -354,26 +430,25 @@
}
my $cust_pay_batch =
- qsearchs('cust_pay_batch', { 'paybatchnum' => $hash{'paybatchnum'} } );
+ qsearchs('cust_pay_batch', { 'paybatchnum' => $hash{'paybatchnum'}+0 } );
unless ( $cust_pay_batch ) {
$dbh->rollback if $oldAutoCommit;
return "unknown paybatchnum $hash{'paybatchnum'}\n";
}
my $custnum = $cust_pay_batch->custnum,
+ my $payby = $cust_pay_batch->payby,
- my $error = $cust_pay_batch->delete;
- if ( $error ) {
- $dbh->rollback if $oldAutoCommit;
- return "error removing paybatchnum $hash{'paybatchnum'}: $error\n";
- }
+ my $new_cust_pay_batch = new FS::cust_pay_batch { $cust_pay_batch->hash };
&{$hook}(\%hash);
if ( &{$approved_condition}(\%hash) ) {
+ $new_cust_pay_batch->status('Approved');
+
my $cust_pay = new FS::cust_pay ( {
'custnum' => $custnum,
- 'payby' => 'CARD',
+ 'payby' => $payby,
'paybatch' => $paybatch,
map { $_ => $hash{$_} } (qw( paid _date payinfo )),
} );
@@ -388,9 +463,81 @@
} elsif ( &{$declined_condition}(\%hash) ) {
+ $new_cust_pay_batch->status('Declined');
+
#this should be configurable... if anybody else ever uses batches
- $cust_pay_batch->cust_main->suspend;
+ # $cust_pay_batch->cust_main->suspend;
+
+ foreach my $part_bill_event (
+ sort { $a->seconds <=> $b->seconds
+ || $a->weight <=> $b->weight
+ || $a->eventpart <=> $b->eventpart }
+ grep { ! qsearch( 'cust_bill_event', {
+ 'invnum' => $cust_pay_batch->invnum,
+ 'eventpart' => $_->eventpart,
+ 'status' => 'done',
+ } )
+ }
+ qsearch( {
+ 'table' => 'part_bill_event',
+ 'hashref' => { 'payby' => 'DCLN',
+ 'disabled' => '', },
+ } )
+ ) {
+ # don't run subsequent events if balance<=0
+ last if $cust_pay_batch->cust_main->balance <= 0;
+
+ warn " calling invoice event (". $part_bill_event->eventcode. ")\n"
+ if $DEBUG > 1;
+ my $cust_main = $cust_pay_batch->cust_main; #for callback
+
+ my $error;
+ {
+ local $SIG{__DIE__}; # don't want Mason __DIE__ handler active
+ $error = eval $part_bill_event->eventcode;
+ }
+
+ my $status = '';
+ my $statustext = '';
+ if ( $@ ) {
+ $status = 'failed';
+ $statustext = $@;
+ } elsif ( $error ) {
+ $status = 'done';
+ $statustext = $error;
+ } else {
+ $status = 'done'
+ }
+
+ #add cust_bill_event
+ my $cust_bill_event = new FS::cust_bill_event {
+ 'invnum' => $cust_pay_batch->invnum,
+ 'eventpart' => $part_bill_event->eventpart,
+ '_date' => time,
+ 'status' => $status,
+ 'statustext' => $statustext,
+ };
+ $error = $cust_bill_event->insert;
+ if ( $error ) {
+ # gah, even with transactions.
+ $dbh->commit if $oldAutoCommit; #well.
+ my $e = 'WARNING: Event run but database not updated - '.
+ 'error inserting cust_bill_event, invnum #'. $cust_pay_batch->invnum.
+ ', eventpart '. $part_bill_event->eventpart.
+ ": $error";
+ warn $e;
+ return $e;
+ }
+
+ }
+
+ }
+
+ my $error = $new_cust_pay_batch->replace($cust_pay_batch);
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return "error updating status of paybatchnum $hash{'paybatchnum'}: $error\n";
}
}
More information about the freeside-commits
mailing list