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
$error = $record->check;
- $error = $record->retriable;
+ #deprecated# $error = $record->retriable;
=head1 DESCRIPTION
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<FS::cust_bill_event>) 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<FS::cust_bill_event>) 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
'';
}
+=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<FS::cust_pay>). 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
+
+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.
+
+=cut
+
+sub decline {
+ my $new = shift;
+ 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. Only if manual approval is enabled.
+ if ( $conf->exists('batch-manual_approval')
+ and 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('Returned payment');
+ }
+ 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