X-Git-Url: http://git.freeside.biz/gitweb/?a=blobdiff_plain;f=FS%2FFS%2Fcust_pay_batch.pm;h=20e88a0dace54f17672e4f9629bfddbc8c1672e7;hb=39b842eecba98e7d86b45ea50548a4c5546090d8;hp=9ef1e1cc100c308f406686a3eeed76763e7ee0bc;hpb=eb4ff7f73c5d4bdf74a3472448b5a195598ff4cd;p=freeside.git diff --git a/FS/FS/cust_pay_batch.pm b/FS/FS/cust_pay_batch.pm index 9ef1e1cc1..20e88a0da 100644 --- a/FS/FS/cust_pay_batch.pm +++ b/FS/FS/cust_pay_batch.pm @@ -9,13 +9,16 @@ use FS::payinfo_Mixin; use FS::cust_main; use FS::cust_bill; -@ISA = qw( FS::payinfo_Mixin FS::Record ); +@ISA = qw( FS::payinfo_Mixin FS::cust_main_Mixin 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; +#@encrypted_fields = ('payinfo'); +sub nohistory_fields { ('payinfo'); } + =head1 NAME FS::cust_pay_batch - Object methods for batch cards @@ -80,7 +83,9 @@ following fields are currently supported: =item country -=item status +=item status - 'Approved' or 'Declined' + +=item error_message - the error returned by the gateway if any =back @@ -204,6 +209,17 @@ sub cust_main { qsearchs( 'cust_main', { 'custnum' => $self->custnum } ); } +=item pay_batch + +Returns the payment batch this payment belongs to (Lby_key($self->batchnum); +} + #you know what, screw this in the new world of events. we should be able to #get the event defs to retry (remove once.pm condition, add every.pm) without #mucking about with statuses of previous cust_event records. right? @@ -260,6 +276,117 @@ sub retriable { ''; } +=item approve PAYBATCH + +Approve this payment. This will replace the existing record with the +same paybatchnum, set its status to 'Approved', and generate a payment +record (L). This should only be called from the batch +import process. + +=cut + +sub approve { + # to break up the Big Wall of Code that is import_results + my $new = shift; + my $paybatch = shift; + my $paybatchnum = $new->paybatchnum; + my $old = qsearchs('cust_pay_batch', { paybatchnum => $paybatchnum }) + or return "paybatchnum $paybatchnum not found"; + return "paybatchnum $paybatchnum already resolved ('".$old->status."')" + if $old->status; + $new->status('Approved'); + my $error = $new->replace($old); + if ( $error ) { + return "error updating status of paybatchnum $paybatchnum: $error\n"; + } + my $cust_pay = new FS::cust_pay ( { + 'custnum' => $new->custnum, + 'payby' => $new->payby, + 'paybatch' => $paybatch, + 'payinfo' => $new->payinfo || $old->payinfo, + 'paid' => $new->paid, + '_date' => $new->_date, + 'usernum' => $new->usernum, + 'batchnum' => $new->batchnum, + } ); + $error = $cust_pay->insert; + if ( $error ) { + return "error inserting payment for paybatchnum $paybatchnum: $error\n"; + } + $cust_pay->cust_main->apply_payments; + return; +} + +=item decline [ REASON ] + +Decline this payment. This will replace the existing record with the +same paybatchnum, set its status to 'Declined', and run collection events +as appropriate. This should only be called from the batch import process. + +REASON is a string description of the decline reason, defaulting to +'Returned payment'. + +=cut + +sub decline { + my $new = shift; + my $reason = shift || 'Returned payment'; + #my $conf = new FS::Conf; + + my $paybatchnum = $new->paybatchnum; + my $old = qsearchs('cust_pay_batch', { paybatchnum => $paybatchnum }) + or return "paybatchnum $paybatchnum not found"; + if ( $old->status ) { + # Handle the case where payments are rejected after the batch has been + # approved. FS::pay_batch::import_results won't allow results to be + # imported to a closed batch unless batch-manual_approval is enabled, + # so we don't check it here. +# if ( $conf->exists('batch-manual_approval') and + if ( lc($old->status) eq 'approved' ) { + # Void the payment + my $cust_pay = qsearchs('cust_pay', { + custnum => $new->custnum, + batchnum => $new->batchnum + }); + # pre-3.0 style + $cust_pay ||= qsearchs('cust_pay', { + custnum => $new->custnum, + paybatch => $new->batchnum + }); + if ( !$cust_pay ) { + # should never happen... + return "failed to revoke paybatchnum $paybatchnum, payment not found"; + } + $cust_pay->void($reason); + } + else { + # normal case: refuse to do anything + return "paybatchnum $paybatchnum already resolved ('".$old->status."')"; + } + } # !$old->status + $new->status('Declined'); + $new->error_message($reason); + my $error = $new->replace($old); + if ( $error ) { + return "error updating status of paybatchnum $paybatchnum: $error\n"; + } + my $due_cust_event = $new->cust_main->due_cust_event( + 'eventtable' => 'cust_pay_batch', + 'objects' => [ $new ], + ); + if ( !ref($due_cust_event) ) { + return $due_cust_event; + } + # XXX breaks transaction integrity + foreach my $cust_event (@$due_cust_event) { + next unless $cust_event->test_conditions; + if ( my $error = $cust_event->do_event() ) { + return $error; + } + } + return; +} + =back =head1 BUGS