summaryrefslogtreecommitdiff
path: root/FS/FS/cust_main.pm
diff options
context:
space:
mode:
authorMitch Jackson <mitch@freeside.biz>2018-09-11 03:23:52 -0400
committerMitch Jackson <mitch@freeside.biz>2018-09-19 12:02:19 -0400
commit94f0030bae0ce3e493b99860901158e30e9651fd (patch)
treeae3576bdc3073d825a424030275f7ca1918675bd /FS/FS/cust_main.pm
parentb9bb2b3bc596c18245199cd799c5f50d3e02ea59 (diff)
RT# 78547 Allow for simulated billing within a transaction
Diffstat (limited to 'FS/FS/cust_main.pm')
-rw-r--r--FS/FS/cust_main.pm45
1 files changed, 37 insertions, 8 deletions
diff --git a/FS/FS/cust_main.pm b/FS/FS/cust_main.pm
index 64b002b..aa8ae2a 100644
--- a/FS/FS/cust_main.pm
+++ b/FS/FS/cust_main.pm
@@ -79,6 +79,7 @@ use FS::sales;
use FS::cust_payby;
use FS::contact;
use FS::reason;
+use FS::Misc::Savepoint;
# 1 is mostly method/subroutine entry and options
# 2 traces progress of some operations
@@ -2441,11 +2442,15 @@ sub cancel_pkgs {
my( $self, %opt ) = @_;
# we're going to cancel services, which is not reversible
+ # unless exports are suppressed
die "cancel_pkgs cannot be run inside a transaction"
- if $FS::UID::AutoCommit == 0;
+ if !$FS::UID::AutoCommit && !$FS::svc_Common::noexport_hack;
+ my $oldAutoCommit = $FS::UID::AutoCommit;
local $FS::UID::AutoCommit = 0;
+ savepoint_create('cancel_pkgs');
+
return ( 'access denied' )
unless $FS::CurrentUser::CurrentUser->access_right('Cancel customer');
@@ -2462,7 +2467,8 @@ sub cancel_pkgs {
my $ban = new FS::banned_pay $cust_payby->_new_banned_pay_hashref;
my $error = $ban->insert;
if ($error) {
- dbh->rollback;
+ savepoint_rollback_and_release('cancel_pkgs');
+ dbh->rollback if $oldAutoCommit;
return ( $error );
}
@@ -2482,13 +2488,14 @@ sub cancel_pkgs {
'time' => $cancel_time );
if ($error) {
warn "Error billing during cancel, custnum ". $self->custnum. ": $error";
- dbh->rollback;
+ savepoint_rollback_and_release('cancel_pkgs');
+ dbh->rollback if $oldAutoCommit;
return ( "Error billing during cancellation: $error" );
}
}
- dbh->commit;
+ savepoint_release('cancel_pkgs');
+ dbh->commit if $oldAutoCommit;
- $FS::UID::AutoCommit = 1;
my @errors;
# now cancel all services, the same way we would for individual packages.
# if any of them fail, cancel the rest anyway.
@@ -2501,11 +2508,23 @@ sub cancel_pkgs {
warn "$me removing ".scalar(@sorted_cust_svc)." service(s) for customer ".
$self->custnum."\n"
if $DEBUG;
+ my $i = 0;
foreach my $cust_svc (@sorted_cust_svc) {
+ my $savepoint = 'cancel_pkgs_'.$i++;
+ savepoint_create( $savepoint );
my $part_svc = $cust_svc->part_svc;
next if ( defined($part_svc) and $part_svc->preserve );
- my $error = $cust_svc->cancel; # immediate cancel, no date option
- push @errors, $error if $error;
+ # immediate cancel, no date option
+ # transactionize individually
+ my $error = try { $cust_svc->cancel } catch { $_ };
+ if ( $error ) {
+ savepoint_rollback_and_release( $savepoint );
+ dbh->rollback if $oldAutoCommit;
+ push @errors, $error;
+ } else {
+ savepoint_release( $savepoint );
+ dbh->commit if $oldAutoCommit;
+ }
}
if (@errors) {
return @errors;
@@ -2520,8 +2539,11 @@ sub cancel_pkgs {
@cprs = @{ delete $opt{'cust_pkg_reason'} };
}
my $null_reason;
+ $i = 0;
foreach (@pkgs) {
my %lopt = %opt;
+ my $savepoint = 'cancel_pkgs_'.$i++;
+ savepoint_create( $savepoint );
if (@cprs) {
my $cpr = shift @cprs;
if ( $cpr ) {
@@ -2541,7 +2563,14 @@ sub cancel_pkgs {
}
}
my $error = $_->cancel(%lopt);
- push @errors, 'pkgnum '.$_->pkgnum.': '.$error if $error;
+ if ( $error ) {
+ savepoint_rollback_and_release( $savepoint );
+ dbh->rollback if $oldAutoCommit;
+ push @errors, 'pkgnum '.$_->pkgnum.': '.$error;
+ } else {
+ savepoint_release( $savepoint );
+ dbh->commit if $oldAutoCommit;
+ }
}
return @errors;