}
}
- my @labels = ();
-
- foreach my $cust_svc (
- qsearch( 'cust_svc', { 'pkgnum' => $self->pkgnum } )
- ) {
- my $part_svc = qsearchs( 'part_svc', { 'svcpart' => $cust_svc->svcpart } );
-
- $part_svc->svcdb =~ /^([\w\-]+)$/ or do {
- $dbh->rollback if $oldAutoCommit;
- return "Illegal svcdb value in part_svc!";
- };
- my $svcdb = $1;
- require "FS/$svcdb.pm";
-
- my $svc = qsearchs( $svcdb, { 'svcnum' => $cust_svc->svcnum } );
- if ($svc) {
- $error = $svc->suspend;
- if ( $error ) {
- $dbh->rollback if $oldAutoCommit;
- return $error;
- }
- my( $label, $value ) = $cust_svc->label;
- push @labels, "$label: $value";
+ my @cust_svc = qsearch( 'cust_svc', { 'pkgnum' => $self->pkgnum } )
+
+ #attempt ordering ala cust_svc_suspend_cascade (without infinite-looping
+ # on the circular dep case)
+ # (this is too simple for multi-level deps, we need to use something
+ # to resolve the DAG properly when possible)
+ my %svcpart = ();
+ $svcpart{$_->svcpart} = 0 foreach @cust_svc;
+ foreach my $svcpart ( keys %svcpart ) {
+ foreach my $part_pkg_link (
+ FS::part_svc_link->by_agentnum($self->cust_main->agentnum,
+ src_svcpart => $svcpart,
+ link_type => 'cust_svc_suspend_cascade'
+ )
+ ) {
+ $svcpart{$part_svc_link->dst_svcpart} = max(
+ $svcpart{$part_svc_link->dst_svcpart},
+ $svcpart{$part_svc_link->src_svcpart} + 1
+ );
}
}
+ @cust_svc = sort { $svcpart{ $a->svcpart } <=> $svcpart{ $b->svcpart } }
+ @cust_svc;
+
+ my @labels = ();
+ foreach my $cust_svc ( @cust_svc ) {
+ $cust_svc->suspend( 'labels_arrayref' => \@labels );
+ }
# suspension fees: if there is a feepart, and it's not an unsuspend fee,
# and this is not a suspend-before-cancel
}
+=item suspend
+
+Suspends the relevant service by calling the B<suspend> method of the associated
+FS::svc_XXX object (i.e. an FS::svc_acct object or FS::svc_domain object).
+
+If there is an error, returns the error, otherwise returns false.
+
+=cut
+
+sub suspend {
+ my( $self, %opt ) = @_;
+
+ $self->part_svc->svcdb =~ /^([\w\-]+)$/ or return 'Illegal part_svc.svcdb';
+ my $svcdb = $1;
+ require "FS/$svcdb.pm";
+
+ my $svc = qsearchs( $svcdb, { 'svcnum' => $self->svcnum } )
+ or return '';
+
+ $error = $svc->suspend;
+ return $error if $error;
+
+ if ( $opt{labels_arryref} ) {
+ my( $label, $value ) = $self->label;
+ push @{ $opt{labels_arrayref} }, "$label: $value";
+ }
+
+ '';
+
+}
+
=item cancel
Cancels the relevant service by calling the B<cancel> method of the associated
=item cust_svc_suspend_cascade
-Suspend the destination service before the source service
+Suspend the destination service after the source service
=back
and return "Automatically unprovision $dst when $src is unprovisioned";
$l eq 'cust_svc_suspend_cascade'
- and return "Suspend $dst before $src";
+ and return "Suspend $dst after $src";
warn "WARNING: unknown part_svc_link.link_type $l\n";
return "$src (unknown link_type $l) $dst";
cust_svc_provision_restrict => 'Require the target service to be provisioned before the source service',
cust_svc_unprovision_restrict => 'Require the target service to be unprovisioned before the source service',
cust_svc_unprovision_cascade => 'Automatically unprovision the target service when the source service is unprovisioned',
- cust_svc_suspend_cascade => 'Suspend the target service before the source service',
+ cust_svc_suspend_cascade => 'Suspend the target service after the source service',
},
},
{ field => 'disabled', type => 'checkbox', value => 'Y' }