X-Git-Url: http://git.freeside.biz/gitweb/?a=blobdiff_plain;f=FS%2FFS%2Fcust_pay_batch.pm;h=f5e6a4bf1c6ef2ef6b8e6870f4a7e62f0d6f252b;hb=573139dbd6c37808697bfa72a3a468bb0980d4dd;hp=573f06f3aef9430c3d8ea62811c074e0bb39cc6c;hpb=cd9740708c8658665101ef6ad667b1afc2cd04ff;p=freeside.git diff --git a/FS/FS/cust_pay_batch.pm b/FS/FS/cust_pay_batch.pm index 573f06f3a..f5e6a4bf1 100644 --- a/FS/FS/cust_pay_batch.pm +++ b/FS/FS/cust_pay_batch.pm @@ -2,11 +2,14 @@ package FS::cust_pay_batch; use strict; use vars qw( @ISA $DEBUG ); +use Carp qw( confess ); +use Business::CreditCard 0.28; use FS::Record qw(dbh qsearch qsearchs); use FS::payinfo_Mixin; -use Business::CreditCard 0.28; +use FS::cust_main; +use FS::cust_bill; -@ISA = qw( FS::Record FS::payinfo_Mixin ); +@ISA = qw( FS::payinfo_Mixin FS::Record ); # 1 is mostly method/subroutine entry and options # 2 traces progress of some operations @@ -32,7 +35,7 @@ FS::cust_pay_batch - Object methods for batch cards $error = $record->check; - $error = $record->retriable; + #deprecated# $error = $record->retriable; =head1 DESCRIPTION @@ -201,19 +204,27 @@ sub cust_main { qsearchs( 'cust_main', { 'custnum' => $self->custnum } ); } -=item retriable +#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? +# +#=item retriable +# +#Marks the corresponding event (see L) for this batched +#credit card payment as retriable. Useful if the corresponding financial +#institution account was declined for temporary reasons and/or a manual +#retry is desired. +# +#Implementation details: For the named customer's invoice, changes the +#statustext of the 'done' (without statustext) event to 'retriable.' +# +#=cut -Marks the corresponding event (see L) for this batched -credit card payment as retriable. Useful if the corresponding financial -institution account was declined for temporary reasons and/or a manual -retry is desired. +sub retriable { -Implementation details: For the named customer's invoice, changes the -statustext of the 'done' (without statustext) event to 'retriable.' + confess "deprecated method cust_pay_batch->retriable called; try removing ". + "the once condition and adding an every condition?"; -=cut - -sub retriable { my $self = shift; local $SIG{HUP} = 'IGNORE'; #Hmm @@ -249,6 +260,110 @@ 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, + } ); + $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, + 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'); + 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