summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Wells <mark@freeside.biz>2016-07-07 20:22:45 -0700
committerMark Wells <mark@freeside.biz>2016-07-07 20:22:45 -0700
commitdb1221a82f407c9ebc782ff03e9cf61115eef8cb (patch)
tree20fc398c481e9ceb02b330c14d6fcdfd8fefebfc
parent6401184cc06d3a324a230490097289d0d6e7fa91 (diff)
parentf609fce353fab43501bf8e3823c613562f29e18d (diff)
Merge branch 'FREESIDE_3_BRANCH' of git.freeside.biz:/home/git/freeside into 3.x
-rw-r--r--FS/FS/cust_pkg.pm206
-rw-r--r--FS/FS/h_svc_acct.pm1
-rw-r--r--FS/FS/h_svc_forward.pm4
-rw-r--r--FS/FS/h_svc_www.pm1
-rw-r--r--FS/FS/svc_acct.pm2
-rwxr-xr-xhttemplate/misc/cancel_pkg.html31
-rwxr-xr-xhttemplate/misc/process/cancel_pkg.html3
-rw-r--r--httemplate/view/cust_main/packages/services.html20
-rw-r--r--httemplate/view/cust_main/packages/status.html2
9 files changed, 226 insertions, 44 deletions
diff --git a/FS/FS/cust_pkg.pm b/FS/FS/cust_pkg.pm
index e6374decf..b5777027b 100644
--- a/FS/FS/cust_pkg.pm
+++ b/FS/FS/cust_pkg.pm
@@ -1090,6 +1090,166 @@ sub cancel_if_expired {
'';
}
+=item uncancel_svc_x
+
+For cancelled cust_pkg, returns a list of new, uninserted FS::svc_X records
+for services that would be inserted by L</uncancel>. Returned objects also
+include the field _h_svc_x, which contains the service history object.
+
+Set pkgnum before inserting.
+
+Accepts the following options:
+
+only_svcnum - arrayref of svcnum, only returns objects for these svcnum
+(and only if they would otherwise be returned by this)
+
+=cut
+
+sub uncancel_svc_x {
+ my ($self, %opt) = @_;
+
+ die 'uncancel_svc_x called on a non-cancelled cust_pkg' unless $self->get('cancel');
+
+ #find historical services within this timeframe before the package cancel
+ # (incompatible with "time" option to cust_pkg->cancel?)
+ my $fuzz = 2 * 60; #2 minutes? too much? (might catch separate unprovision)
+ # too little? (unprovisioing export delay?)
+ my($end, $start) = ( $self->get('cancel'), $self->get('cancel') - $fuzz );
+ my @h_cust_svc = $self->h_cust_svc( $end, $start );
+
+ my @svc_x;
+ foreach my $h_cust_svc (@h_cust_svc) {
+ next if $opt{'only_svcnum'} && !(grep { $_ == $h_cust_svc->svcnum } @{$opt{'only_svcnum'}});
+ # filter out services that still exist on this package (ie preserved svcs)
+ # but keep services that have since been provisioned on another package (for informational purposes)
+ next if qsearchs('cust_svc',{ 'svcnum' => $h_cust_svc->svcnum, 'pkgnum' => $self->pkgnum });
+ my $h_svc_x = $h_cust_svc->h_svc_x( $end, $start );
+ next unless $h_svc_x; # this probably doesn't happen, but just in case
+ (my $table = $h_svc_x->table) =~ s/^h_//;
+ require "FS/$table.pm";
+ my $class = "FS::$table";
+ my $svc_x = $class->new( {
+ 'svcpart' => $h_cust_svc->svcpart,
+ '_h_svc_x' => $h_svc_x,
+ map { $_ => $h_svc_x->get($_) } fields($table)
+ } );
+
+ # radius_usergroup
+ if ( $h_svc_x->isa('FS::h_svc_Radius_Mixin') ) {
+ $svc_x->usergroup( [ $h_svc_x->h_usergroup($end, $start) ] );
+ }
+
+ #these are pretty rare, but should handle them
+ # - dsl_device (mac addresses)
+ # - phone_device (mac addresses)
+ # - dsl_note (ikano notes)
+ # - domain_record (i.e. restore DNS information w/domains)
+ # - inventory_item(?) (inventory w/un-cancelling service?)
+ # - nas (svc_broaband nas stuff)
+ #this stuff is unused in the wild afaik
+ # - mailinglistmember
+ # - router.svcnum?
+ # - svc_domain.parent_svcnum?
+ # - acct_snarf (ancient mail fetching config)
+ # - cgp_rule (communigate)
+ # - cust_svc_option (used by our Tron stuff)
+ # - acct_rt_transaction (used by our time worked stuff)
+
+ push @svc_x, $svc_x;
+ }
+ return @svc_x;
+}
+
+=item uncancel_svc_summary
+
+Returns an array of hashrefs, one for each service that could
+potentially be reprovisioned by L</uncancel>, with the following keys:
+
+svcpart
+
+svc
+
+uncancel_svcnum
+
+label - from history table if not currently calculable, undefined if it can't be loaded
+
+reprovisionable - 1 if test reprovision succeeded, otherwise 0
+
+num_cust_svc - number of svcs for this svcpart, only if summarizing (see below)
+
+Cannot be run from within a transaction. Performs inserts
+to test the results, and then rolls back the transaction.
+Does not perform exports, so does not catch if export would fail.
+
+Also accepts the following options:
+
+no_test_reprovision - skip the test inserts (reprovisionable field will not exist)
+
+summarize_size - if true, returns a single summary record for svcparts with at
+least this many svcs, will have key num_cust_svc but not uncancel_svcnum, label or reprovisionable
+
+=cut
+
+sub uncancel_svc_summary {
+ my ($self, %opt) = @_;
+
+ die 'uncancel_svc_summary called on a non-cancelled cust_pkg' unless $self->get('cancel');
+ die 'uncancel_svc_summary called from within a transaction' unless $FS::UID::AutoCommit;
+
+ local $FS::svc_Common::noexport_hack = 1; # very important not to run exports!!!
+ local $FS::UID::AutoCommit = 0;
+
+ # sort by svcpart, to check summarize_size
+ my $uncancel_svc_x = {};
+ foreach my $svc_x (sort { $a->{'svcpart'} <=> $b->{'svcpart'} } $self->uncancel_svc_x) {
+ $uncancel_svc_x->{$svc_x->svcpart} = [] unless $uncancel_svc_x->{$svc_x->svcpart};
+ push @{$uncancel_svc_x->{$svc_x->svcpart}}, $svc_x;
+ }
+
+ my @out;
+ foreach my $svcpart (keys %$uncancel_svc_x) {
+ my @svcpart_svc_x = @{$uncancel_svc_x->{$svcpart}};
+ if ($opt{'summarize_size'} && (@svcpart_svc_x >= $opt{'summarize_size'})) {
+ my $svc_x = $svcpart_svc_x[0]; #grab first one for access to $part_svc
+ my $part_svc = $svc_x->part_svc;
+ push @out, {
+ 'svcpart' => $part_svc->svcpart,
+ 'svc' => $part_svc->svc,
+ 'num_cust_svc' => scalar(@svcpart_svc_x),
+ };
+ } else {
+ foreach my $svc_x (@svcpart_svc_x) {
+ my $part_svc = $svc_x->part_svc;
+ my $out = {
+ 'svcpart' => $part_svc->svcpart,
+ 'svc' => $part_svc->svc,
+ 'uncancel_svcnum' => $svc_x->get('_h_svc_x')->svcnum,
+ };
+ $svc_x->pkgnum($self->pkgnum); # provisioning services on a canceled package, will be rolled back
+ my $insert_error;
+ unless ($opt{'no_test_reprovision'}) {
+ # avoid possibly fatal errors from missing linked records
+ eval { $insert_error = $svc_x->insert };
+ $insert_error ||= $@;
+ }
+ if ($opt{'no_test_reprovision'} or $insert_error) {
+ # avoid possibly fatal errors from missing linked records
+ eval { $out->{'label'} = $svc_x->label };
+ eval { $out->{'label'} = $svc_x->get('_h_svc_x')->label } unless defined($out->{'label'});
+ $out->{'reprovisionable'} = 0 unless $opt{'no_test_reprovision'};
+ } else {
+ $out->{'label'} = $svc_x->label;
+ $out->{'reprovisionable'} = 1;
+ }
+ push @out, $out;
+ }
+ }
+ }
+
+ dbh->rollback;
+ return @out;
+}
+
=item uncancel
"Un-cancels" this package: Orders a new package with the same custnum, pkgpart,
@@ -1102,6 +1262,8 @@ svc_fatal: service provisioning errors are fatal
svc_errors: pass an array reference, will be filled in with any provisioning errors
+only_svcnum: arrayref, only attempt to re-provision these cancelled services
+
main_pkgnum: link the package as a supplemental package of this one. For
internal use only.
@@ -1165,32 +1327,12 @@ sub uncancel {
# insert services
##
- #find historical services within this timeframe before the package cancel
- # (incompatible with "time" option to cust_pkg->cancel?)
- my $fuzz = 2 * 60; #2 minutes? too much? (might catch separate unprovision)
- # too little? (unprovisioing export delay?)
- my($end, $start) = ( $self->get('cancel'), $self->get('cancel') - $fuzz );
- my @h_cust_svc = $self->h_cust_svc( $end, $start );
-
my @svc_errors;
- foreach my $h_cust_svc (@h_cust_svc) {
- my $h_svc_x = $h_cust_svc->h_svc_x( $end, $start );
- #next unless $h_svc_x; #should this happen?
- (my $table = $h_svc_x->table) =~ s/^h_//;
- require "FS/$table.pm";
- my $class = "FS::$table";
- my $svc_x = $class->new( {
- 'pkgnum' => $cust_pkg->pkgnum,
- 'svcpart' => $h_cust_svc->svcpart,
- map { $_ => $h_svc_x->get($_) } fields($table)
- } );
-
- # radius_usergroup
- if ( $h_svc_x->isa('FS::h_svc_Radius_Mixin') ) {
- $svc_x->usergroup( [ $h_svc_x->h_usergroup($end, $start) ] );
- }
+ foreach my $svc_x ($self->uncancel_svc_x('only_svcnum' => $options{'only_svcnum'})) {
+ $svc_x->pkgnum($cust_pkg->pkgnum);
my $svc_error = $svc_x->insert;
+
if ( $svc_error ) {
if ( $options{svc_fatal} ) {
$dbh->rollback if $oldAutoCommit;
@@ -1214,23 +1356,7 @@ sub uncancel {
}
} # svc_fatal
} # svc_error
- } #foreach $h_cust_svc
-
- #these are pretty rare, but should handle them
- # - dsl_device (mac addresses)
- # - phone_device (mac addresses)
- # - dsl_note (ikano notes)
- # - domain_record (i.e. restore DNS information w/domains)
- # - inventory_item(?) (inventory w/un-cancelling service?)
- # - nas (svc_broaband nas stuff)
- #this stuff is unused in the wild afaik
- # - mailinglistmember
- # - router.svcnum?
- # - svc_domain.parent_svcnum?
- # - acct_snarf (ancient mail fetching config)
- # - cgp_rule (communigate)
- # - cust_svc_option (used by our Tron stuff)
- # - acct_rt_transaction (used by our time worked stuff)
+ } #foreach uncancel_svc_x
##
# also move over any services that didn't unprovision at cancellation
diff --git a/FS/FS/h_svc_acct.pm b/FS/FS/h_svc_acct.pm
index f525f8206..7416054bc 100644
--- a/FS/FS/h_svc_acct.pm
+++ b/FS/FS/h_svc_acct.pm
@@ -28,6 +28,7 @@ FS::h_svc_acct - Historical account objects
sub svc_domain {
my $self = shift;
+ $_[0] ||= $self->history_date;
qsearchs( 'h_svc_domain',
{ 'svcnum' => $self->domsvc },
FS::h_svc_domain->sql_h_searchs(@_),
diff --git a/FS/FS/h_svc_forward.pm b/FS/FS/h_svc_forward.pm
index 25b203904..c0eeb3fc5 100644
--- a/FS/FS/h_svc_forward.pm
+++ b/FS/FS/h_svc_forward.pm
@@ -32,6 +32,8 @@ FS::h_svc_forward - Historical mail forwarding alias objects
sub srcsvc_acct {
my $self = shift;
+
+ $_[0] ||= $self->history_date;
my $h_svc_acct = qsearchs(
'h_svc_acct',
{ 'svcnum' => $self->srcsvc },
@@ -52,6 +54,8 @@ sub srcsvc_acct {
sub dstsvc_acct {
my $self = shift;
+
+ $_[0] ||= $self->history_date;
my $h_svc_acct = qsearchs(
'h_svc_acct',
{ 'svcnum' => $self->dstsvc },
diff --git a/FS/FS/h_svc_www.pm b/FS/FS/h_svc_www.pm
index 2a3b6dca6..20002214b 100644
--- a/FS/FS/h_svc_www.pm
+++ b/FS/FS/h_svc_www.pm
@@ -33,6 +33,7 @@ sub domain_record {
carp 'Called FS::h_svc_www->domain_record on svcnum ' . $self->svcnum if $DEBUG;
+ $_[0] ||= $self->history_date;
my $domain_record = qsearchs(
'h_domain_record',
{ 'recnum' => $self->recnum },
diff --git a/FS/FS/svc_acct.pm b/FS/FS/svc_acct.pm
index 74ddcd5c7..a86db9c0a 100644
--- a/FS/FS/svc_acct.pm
+++ b/FS/FS/svc_acct.pm
@@ -738,7 +738,7 @@ sub insert {
#welcome email
my @welcome_exclude_svcparts = $conf->config('svc_acct_welcome_exclude');
- unless ( grep { $_ eq $self->svcpart } @welcome_exclude_svcparts ) {
+ unless ($FS::svc_Common::noexport_hack or ( grep { $_ eq $self->svcpart } @welcome_exclude_svcparts )) {
my $error = '';
my $msgnum = $conf->config('welcome_msgnum', $agentnum);
if ( $msgnum ) {
diff --git a/httemplate/misc/cancel_pkg.html b/httemplate/misc/cancel_pkg.html
index 0f33f4dfb..d77c47ed6 100755
--- a/httemplate/misc/cancel_pkg.html
+++ b/httemplate/misc/cancel_pkg.html
@@ -45,12 +45,41 @@
} &>
<& /elements/tr-checkbox.html,
- 'label' => mt("Uncancel even if a service can't be re-provisioned"),
+ 'label' => mt("Uncancel even if service reprovisioning fails"),
'field' => 'svc_not_fatal',
'value' => 'Y',
&>
% $date_init = 1;
+% my @uncancel_svcs = sort { $b->{'reprovisionable'} <=> $a->{'reprovisionable'} }
+% sort { $a->{'svcpart'} <=> $b->{'svcpart'} }
+% $cust_pkg->uncancel_svc_summary();
+% if (@uncancel_svcs) {
+<TR><TD COLSPAN="2">&nbsp;</TD></TR>
+<TR><TH ALIGN="right"><% emt("Re-provision the following services") %></TH><TD></TD>
+% foreach my $uncancel_svc (@uncancel_svcs) {
+% my $uncancel_curr_value = $uncancel_svc->{'uncancel_svcnum'};
+% my $uncancel_disabled = '';
+% my $uncancel_postfix = '';
+% if ($cgi->param('error')) {
+% $uncancel_curr_value = '' unless grep { $_ == $uncancel_svc->{'uncancel_svcnum'} } $cgi->param('only_svcnum');
+% }
+% unless ($uncancel_svc->{'reprovisionable'}) {
+% $uncancel_curr_value = '';
+% $uncancel_disabled = 1;
+% $uncancel_postfix = '<I>(' . emt('Cannot be reprovisioned') . ')</I>';
+% }
+ <& /elements/tr-checkbox.html,
+ 'label' => $uncancel_svc->{'svc'} . ': ' . $uncancel_svc->{'label'},
+ 'field' => 'only_svcnum',
+ 'value' => $uncancel_svc->{'uncancel_svcnum'},
+ 'curr_value' => $uncancel_curr_value,
+ 'disabled' => $uncancel_disabled,
+ 'cell_style' => 'font-weight: normal',
+ 'postfix' => $uncancel_postfix,
+ &>
+% }
+% }
% }
% unless ( $method eq 'resume' || $method eq 'uncancel' ) {
diff --git a/httemplate/misc/process/cancel_pkg.html b/httemplate/misc/process/cancel_pkg.html
index 6972a49bf..eb3b2efe6 100755
--- a/httemplate/misc/process/cancel_pkg.html
+++ b/httemplate/misc/process/cancel_pkg.html
@@ -85,6 +85,8 @@ my $bill =
my $svc_fatal = ( $cgi->param('svc_not_fatal') ne 'Y' );
+my $only_svcnum = ($method eq 'uncancel') ? [ $cgi->param('only_svcnum') ] : undef;
+
$error ||= $cust_pkg->$method( 'reason' => $reasonnum,
'date' => $date,
'resume_date' => $resume_date,
@@ -92,6 +94,7 @@ $error ||= $cust_pkg->$method( 'reason' => $reasonnum,
'bill' => $bill,
'svc_fatal' => $svc_fatal,
'options' => $options,
+ 'only_svcnum' => $only_svcnum,
);
if ($error) {
diff --git a/httemplate/view/cust_main/packages/services.html b/httemplate/view/cust_main/packages/services.html
index 39055f49a..a23a4c2fe 100644
--- a/httemplate/view/cust_main/packages/services.html
+++ b/httemplate/view/cust_main/packages/services.html
@@ -105,9 +105,25 @@ function clearhint_search_cust_svc(obj, str) {
</TD>
</TR>
-% }
+% }
+
+% } #foreach part_svc
+
+% if ($cust_pkg->get('cancel')) {
+% foreach my $svc (
+% $cust_pkg->uncancel_svc_summary('summarize_size' => $opt{'cust_pkg-large_pkg_size'}, 'no_test_reprovision' => 1)
+% ) {
+ <TR>
+ <TD ALIGN="right" VALIGN="top"><% $svc->{'svc'} |h %></TD>
+ <TD STYLE="padding-bottom:0px; font-style: italic">
+ <% $svc->{'num_cust_svc'}
+ ? $svc->{'num_cust_svc'} . ' ' . emt('services in history')
+ : (defined($svc->{'label'}) ? $svc->{'label'} : emt('(cannot load svc label)')) |h %>
+ </TD>
+ </TR>
+% }
+% }
-% }
</TABLE>
</TD>
diff --git a/httemplate/view/cust_main/packages/status.html b/httemplate/view/cust_main/packages/status.html
index a6bd0cef4..12608ee2c 100644
--- a/httemplate/view/cust_main/packages/status.html
+++ b/httemplate/view/cust_main/packages/status.html
@@ -679,6 +679,8 @@ sub pkg_uncancel_link {
'actionlabel' => emt('Un-cancel'),
#'color' => #?
'cust_pkg' => shift,
+ 'width' => 960,
+ 'height' => 740,
)
}