use base qw( FS::otaker_Mixin FS::payinfo_transaction_Mixin FS::cust_main_Mixin
FS::Record );
use vars qw( $DEBUG $me $conf @encrypted_fields
- $unsuspendauto $ignore_noapply
+ $ignore_noapply
);
use Date::Format;
use Business::CreditCard;
#ask FS::UID to run this stuff for us later
FS::UID->install_callback( sub {
$conf = new FS::Conf;
- $unsuspendauto = $conf->exists('unsuspendauto');
} );
@encrypted_fields = ('payinfo');
$dbh->commit or die $dbh->errstr if $oldAutoCommit;
- #false laziness w/ cust_credit::insert
- if ( $unsuspendauto && $old_balance && $cust_main->balance <= 0 ) {
- my @errors = $cust_main->unsuspend;
- #return
- # side-fx with nested transactions? upstack rolls back?
- warn "WARNING:Errors unsuspending customer ". $cust_main->custnum. ": ".
- join(' / ', @errors)
- if @errors;
- }
- #eslaf
+ # possibly trigger package unsuspend, doesn't abort transaction on failure
+ $self->unsuspend_balance if $old_balance;
#bill setup fees for voip_cdr bill_every_call packages
#some false laziness w/search in freeside-cdrd
warn "can't send payment receipt/statement: $error" if $error;
}
+ #run payment events immediately
+ my $due_cust_event = $self->cust_main->due_cust_event(
+ 'eventtable' => 'cust_pay',
+ 'objects' => [ $self ],
+ );
+ if ( !ref($due_cust_event) ) {
+ warn "Error searching for cust_pay billing events: $due_cust_event\n";
+ } else {
+ foreach my $cust_event (@$due_cust_event) {
+ next unless $cust_event->test_conditions;
+ if ( my $error = $cust_event->do_event() ) {
+ warn "Error running cust_pay billing event: $error\n";
+ }
+ }
+ }
+
'';
}
return '';
}
+### refund_to_unapply/unapply_refund false laziness with FS::cust_credit
+
+=item refund_to_unapply
+
+Returns L<FS::cust_pay_refund> objects that will be deleted by L</unapply_refund>
+(all currently applied refunds that aren't closed.)
+Returns empty list if payment itself is closed.
+
+=cut
+
+sub refund_to_unapply {
+ my $self = shift;
+ return () if $self->closed;
+ qsearch({
+ 'table' => 'cust_pay_refund',
+ 'hashref' => { 'paynum' => $self->paynum },
+ 'addl_from' => 'LEFT JOIN cust_refund USING (refundnum)',
+ 'extra_sql' => "AND cust_refund.closed IS NULL AND cust_refund.source_paynum IS NULL",
+ });
+}
+
+=item unapply_refund
+
+Deletes all objects returned by L</refund_to_unapply>.
+
+=cut
+
+sub unapply_refund {
+ my $self = shift;
+
+ local $SIG{HUP} = 'IGNORE';
+ local $SIG{INT} = 'IGNORE';
+ local $SIG{QUIT} = 'IGNORE';
+ local $SIG{TERM} = 'IGNORE';
+ local $SIG{TSTP} = 'IGNORE';
+ local $SIG{PIPE} = 'IGNORE';
+
+ my $oldAutoCommit = $FS::UID::AutoCommit;
+ local $FS::UID::AutoCommit = 0;
+
+ foreach my $cust_pay_refund ($self->refund_to_unapply) {
+ my $error = $cust_pay_refund->delete;
+ if ($error) {
+ dbh->rollback if $oldAutoCommit;
+ return $error;
+ }
+ }
+
+ dbh->commit or die dbh->errstr if $oldAutoCommit;
+ return '';
+}
+
=back
=head1 CLASS METHODS
}
} elsif ( !$error ) { #normal case: apply payments as usual
- $cust_pay->cust_main->apply_payments;
+ $cust_pay->cust_main->apply_payments( 'manual'=>1 );
}
}
Returns an SQL fragment to retreive the unapplied amount.
-=cut
+=cut
sub unapplied_sql {
my ($class, $start, $end) = @_;
my $cust_pay = shift;
my $cust_main = $cust_pay->cust_main
or return "can't find customer to which payments apply";
- my $error = $cust_main->apply_payments_and_credits;
+ my $error = $cust_main->apply_payments_and_credits( 'manual'=>1 );
return $error
? "can't apply payments to customer ".$cust_pay->custnum."$error"
: '';