[freeside-commits] branch FREESIDE_4_BRANCH updated. 8adb02e89430ddfe7308ed646baccc1407be7de9

Jonathan Prykop jonathan at 420.am
Thu Aug 6 21:37:59 PDT 2015


The branch, FREESIDE_4_BRANCH has been updated
       via  8adb02e89430ddfe7308ed646baccc1407be7de9 (commit)
       via  4cfd400b382dc16715f33a3ffc1a127db97542a4 (commit)
      from  0e54a9a082024bbf9e4f498dddf22c5aedc7b55c (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 8adb02e89430ddfe7308ed646baccc1407be7de9
Author: Jonathan Prykop <jonathan at freeside.biz>
Date:   Thu Aug 6 23:11:20 2015 -0500

    RT#18361: Delay package from billing until services are provisioned [rename method]

diff --git a/FS/FS/cust_svc.pm b/FS/FS/cust_svc.pm
index c5099fc..974af67 100644
--- a/FS/FS/cust_svc.pm
+++ b/FS/FS/cust_svc.pm
@@ -121,7 +121,7 @@ sub insert {
   my $error = $self->SUPER::insert;
 
   #check if this releases a hold (see FS::pkg_svc provision_hold)
-  $error ||= $self->_provision_hold;
+  $error ||= $self->_check_provision_hold;
 
   if ( $error ) {
     $dbh->rollback if $oldAutoCommit;
@@ -460,7 +460,7 @@ sub replace {
   } # if this is a location change
 
   #check if this releases a hold (see FS::pkg_svc provision_hold)
-  $error ||= $new->_provision_hold;
+  $error ||= $new->_check_provision_hold;
 
   if ( $error ) {
     $dbh->rollback if $oldAutoCommit;
@@ -1246,7 +1246,7 @@ sub smart_search_param {
 # then removes hold from pkg
 # returns $error or '' on success,
 # does not indicate if pkg status was changed
-sub _provision_hold {
+sub _check_provision_hold {
   my $self = shift;
 
   # check status of cust_pkg

commit 4cfd400b382dc16715f33a3ffc1a127db97542a4
Author: Jonathan Prykop <jonathan at freeside.biz>
Date:   Fri Jul 31 01:33:11 2015 -0500

    RT#18361: Delay package from billing until services are provisioned

diff --git a/FS/FS/Schema.pm b/FS/FS/Schema.pm
index c8b9b63..184c6c9 100644
--- a/FS/FS/Schema.pm
+++ b/FS/FS/Schema.pm
@@ -3543,6 +3543,7 @@ sub tables_hashref {
         'primary_svc',   'char', 'NULL', 1, '', '', 
         'hidden',        'char', 'NULL', 1, '', '',
         'bulk_skip',     'char', 'NULL', 1, '', '',
+        'provision_hold', 'char', 'NULL', 1, '', '',
       ],
       'primary_key'  => 'pkgsvcnum',
       'unique'       => [ ['pkgpart', 'svcpart'] ],
diff --git a/FS/FS/cust_pkg.pm b/FS/FS/cust_pkg.pm
index fbecd8d..c5a3d2e 100644
--- a/FS/FS/cust_pkg.pm
+++ b/FS/FS/cust_pkg.pm
@@ -3389,28 +3389,33 @@ Returns a list of FS::part_svc objects representing services included in this
 package but not yet provisioned.  Each FS::part_svc object also has an extra
 field, I<num_avail>, which specifies the number of available services.
 
+Accepts option I<provision_hold>;  if true, only returns part_svc for which the
+associated pkg_svc has the provision_hold flag set.
+
 =cut
 
 sub available_part_svc {
   my $self = shift;
+  my %opt  = @_;
 
   my $pkg_quantity = $self->quantity || 1;
 
   grep { $_->num_avail > 0 }
-    map {
-          my $part_svc = $_->part_svc;
-          $part_svc->{'Hash'}{'num_avail'} = #evil encapsulation-breaking
-            $pkg_quantity * $_->quantity - $self->num_cust_svc($_->svcpart);
-
-	  # more evil encapsulation breakage
-	  if($part_svc->{'Hash'}{'num_avail'} > 0) {
-	    my @exports = $part_svc->part_export_did;
-	    $part_svc->{'Hash'}{'can_get_dids'} = scalar(@exports);
-	  }
-
-          $part_svc;
-        }
-      $self->part_pkg->pkg_svc;
+  map {
+    my $part_svc = $_->part_svc;
+    $part_svc->{'Hash'}{'num_avail'} = #evil encapsulation-breaking
+    $pkg_quantity * $_->quantity - $self->num_cust_svc($_->svcpart);
+
+    # more evil encapsulation breakage
+    if ($part_svc->{'Hash'}{'num_avail'} > 0) {
+      my @exports = $part_svc->part_export_did;
+      $part_svc->{'Hash'}{'can_get_dids'} = scalar(@exports);
+	}
+
+    $part_svc;
+  }
+  grep { $opt{'provision_hold'} ? $_->provision_hold : 1 }
+  $self->part_pkg->pkg_svc;
 }
 
 =item part_svc [ OPTION => VALUE ... ]
diff --git a/FS/FS/cust_svc.pm b/FS/FS/cust_svc.pm
index 986c5ae..c5099fc 100644
--- a/FS/FS/cust_svc.pm
+++ b/FS/FS/cust_svc.pm
@@ -102,6 +102,37 @@ sub table { 'cust_svc'; }
 Adds this service to the database.  If there is an error, returns the error,
 otherwise returns false.
 
+=cut
+
+sub insert {
+  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;
+  my $dbh = dbh;
+
+  my $error = $self->SUPER::insert;
+
+  #check if this releases a hold (see FS::pkg_svc provision_hold)
+  $error ||= $self->_provision_hold;
+
+  if ( $error ) {
+    $dbh->rollback if $oldAutoCommit;
+    return $error if $error
+  }
+
+  $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+  ''; #no error
+
+}
+
 =item delete
 
 Deletes this service from the database.  If there is an error, returns the
@@ -428,6 +459,9 @@ sub replace {
     } # if ($svc_x->locationnum)
   } # if this is a location change
 
+  #check if this releases a hold (see FS::pkg_svc provision_hold)
+  $error ||= $new->_provision_hold;
+
   if ( $error ) {
     $dbh->rollback if $oldAutoCommit;
     return $error if $error
@@ -1206,6 +1240,35 @@ sub smart_search_param {
   );
 }
 
+# If the associated cust_pkg is 'on hold'
+# and the associated pkg_svc has the provision_hold flag
+# and there are no more available_part_svcs on the cust_pkg similarly flagged,
+# then removes hold from pkg
+# returns $error or '' on success,
+# does not indicate if pkg status was changed
+sub _provision_hold {
+  my $self = shift;
+
+  # check status of cust_pkg
+  my $cust_pkg = $self->cust_pkg;
+  return '' unless $cust_pkg->status eq 'on hold';
+
+  # check flag on this svc
+  # small false laziness with $self->pkg_svc
+  # to avoid looking up cust_pkg twice
+  my $pkg_svc  = qsearchs( 'pkg_svc', {
+    'svcpart' => $self->svcpart,
+    'pkgpart' => $cust_pkg->pkgpart,
+  });
+  return '' unless $pkg_svc->provision_hold;
+
+  # check for any others available with that flag
+  return '' if $cust_pkg->available_part_svc( 'provision_hold' => 1 );
+
+  # conditions met, remove hold
+  return $cust_pkg->unsuspend;
+}
+
 sub _upgrade_data {
   my $class = shift;
 
diff --git a/FS/FS/part_pkg.pm b/FS/FS/part_pkg.pm
index 498da8a..97bce45 100644
--- a/FS/FS/part_pkg.pm
+++ b/FS/FS/part_pkg.pm
@@ -183,7 +183,8 @@ I<custnum_ref> and I<options>.
 If I<pkg_svc> is set to a hashref with svcparts as keys and quantities as
 values, appropriate FS::pkg_svc records will be inserted.  I<hidden_svc> can 
 be set to a hashref of svcparts and flag values ('Y' or '') to set the 
-'hidden' field in these records.
+'hidden' field in these records, and I<provision_hold> can be set similarly
+for the 'provision_hold' field in these records.
 
 If I<primary_svc> is set to the svcpart of the primary service, the appropriate
 FS::pkg_svc record will be updated.
@@ -293,6 +294,7 @@ sub insert {
     warn "  inserting pkg_svc records" if $DEBUG;
     my $pkg_svc = $options{'pkg_svc'} || {};
     my $hidden_svc = $options{'hidden_svc'} || {};
+    my $provision_hold = $options{'provision_hold'} || {};
     foreach my $part_svc ( qsearch('part_svc', {} ) ) {
       my $quantity = $pkg_svc->{$part_svc->svcpart} || 0;
       my $primary_svc =
@@ -306,6 +308,7 @@ sub insert {
         'quantity'    => $quantity, 
         'primary_svc' => $primary_svc,
         'hidden'      => $hidden_svc->{$part_svc->svcpart},
+        'provision_hold' => $provision_hold->{$part_svc->svcpart},
       } );
       my $error = $pkg_svc->insert;
       if ( $error ) {
@@ -386,15 +389,15 @@ sub delete {
 Replaces OLD_RECORD with this one in the database.  If there is an error,
 returns the error, otherwise returns false.
 
-Currently available options are: I<pkg_svc>, I<hidden_svc>, I<primary_svc> 
-and I<options>
+Currently available options are: I<pkg_svc>, I<hidden_svc>, I<primary_svc>,
+I<bulk_skip>, I<provision_hold> and I<options>
 
 If I<pkg_svc> is set to a hashref with svcparts as keys and quantities as
 values, the appropriate FS::pkg_svc records will be replaced.  I<hidden_svc>
 can be set to a hashref of svcparts and flag values ('Y' or '') to set the 
-'hidden' field in these records.  I<bulk_skip> can be set to a hashref of
-svcparts and flag values ('Y' or '') to set the 'bulk_skip' field in those
-records.
+'hidden' field in these records.  I<bulk_skip> and I<provision_hold> can be set 
+to a hashref of svcparts and flag values ('Y' or '') to set the respective field 
+in those records.
 
 If I<primary_svc> is set to the svcpart of the primary service, the appropriate
 FS::pkg_svc record will be updated.
@@ -532,12 +535,14 @@ sub replace {
   my $pkg_svc = $options->{'pkg_svc'};
   my $hidden_svc = $options->{'hidden_svc'} || {};
   my $bulk_skip  = $options->{'bulk_skip'} || {};
+  my $provision_hold = $options->{'provision_hold'} || {};
   if ( $pkg_svc ) { # if it wasn't passed, don't change existing pkg_svcs
 
     foreach my $part_svc ( qsearch('part_svc', {} ) ) {
       my $quantity  = $pkg_svc->{$part_svc->svcpart} || 0;
       my $hidden    = $hidden_svc->{$part_svc->svcpart} || '';
       my $bulk_skip = $bulk_skip->{$part_svc->svcpart} || '';
+      my $provision_hold = $provision_hold->{$part_svc->svcpart} || '';
       my $primary_svc =
         ( defined($options->{'primary_svc'}) && $options->{'primary_svc'}
           && $options->{'primary_svc'} == $part_svc->svcpart
@@ -554,18 +559,21 @@ sub replace {
       my $old_primary_svc = '';
       my $old_hidden = '';
       my $old_bulk_skip = '';
+      my $old_provision_hold = '';
       if ( $old_pkg_svc ) {
         $old_quantity = $old_pkg_svc->quantity;
         $old_primary_svc = $old_pkg_svc->primary_svc 
           if $old_pkg_svc->dbdef_table->column('primary_svc'); # is this needed?
         $old_hidden = $old_pkg_svc->hidden;
-        $old_bulk_skip = $old_pkg_svc->old_bulk_skip;
+        $old_bulk_skip = $old_pkg_svc->old_bulk_skip; # should this just be bulk_skip?
+        $old_provision_hold = $old_pkg_svc->provision_hold;
       }
    
       next unless $old_quantity    != $quantity
                || $old_primary_svc ne $primary_svc
                || $old_hidden      ne $hidden
-               || $old_bulk_skip   ne $bulk_skip;
+               || $old_bulk_skip   ne $bulk_skip
+               || $old_provision_hold ne $provision_hold;
     
       my $new_pkg_svc = new FS::pkg_svc( {
         'pkgsvcnum'   => ( $old_pkg_svc ? $old_pkg_svc->pkgsvcnum : '' ),
@@ -575,6 +583,7 @@ sub replace {
         'primary_svc' => $primary_svc,
         'hidden'      => $hidden,
         'bulk_skip'   => $bulk_skip,
+        'provision_hold' => $provision_hold,
       } );
       my $error = $old_pkg_svc
                     ? $new_pkg_svc->replace($old_pkg_svc)
diff --git a/FS/FS/pkg_svc.pm b/FS/FS/pkg_svc.pm
index 4efffd9..b2dc870 100644
--- a/FS/FS/pkg_svc.pm
+++ b/FS/FS/pkg_svc.pm
@@ -47,6 +47,8 @@ definition includes
 
 =item hidden - 'Y' to hide this service on invoices, null otherwise.
 
+=item provision_hold - 'Y' to release package hold when all services marked with this are provisioned
+
 =back
 
 =head1 METHODS
@@ -107,6 +109,7 @@ sub check {
     || $self->ut_number('svcpart')
     || $self->ut_number('quantity')
     || $self->ut_enum('hidden', [ '', 'Y' ] )
+    || $self->ut_flag('provision_hold')
   ;
   return $error if $error;
 
diff --git a/httemplate/edit/process/part_pkg.cgi b/httemplate/edit/process/part_pkg.cgi
index 61a6337..b804202 100755
--- a/httemplate/edit/process/part_pkg.cgi
+++ b/httemplate/edit/process/part_pkg.cgi
@@ -160,6 +160,7 @@ my $args_callback = sub {
   my @svcparts = map { $_->svcpart } qsearch('part_svc', {});
   my %pkg_svc    = map { $_ => scalar($cgi->param("pkg_svc$_"  )) } @svcparts;
   my %hidden_svc = map { $_ => scalar($cgi->param("hidden$_"   )) } @svcparts;
+  my %provision_hold = map { $_ => scalar($cgi->param("provision_hold$_"   )) } @svcparts;
   my %bulk_skip  = map { $_ => ( $cgi->param("no_bulk_skip$_") eq 'Y'
                                    ? '' : 'Y'
                                )
@@ -167,6 +168,7 @@ my $args_callback = sub {
 
   push @args, 'pkg_svc'    => \%pkg_svc,
               'hidden_svc' => \%hidden_svc,
+              'provision_hold' => \%provision_hold,
               'bulk_skip'  => \%bulk_skip;
 
   ###
diff --git a/httemplate/elements/tr-pkg_svc.html b/httemplate/elements/tr-pkg_svc.html
index a44c5b9..cfef51c 100644
--- a/httemplate/elements/tr-pkg_svc.html
+++ b/httemplate/elements/tr-pkg_svc.html
@@ -45,6 +45,12 @@
 %  } else {
 %    $bulk_skip = $pkg_svc->bulk_skip;
 %  }
+%  my $provision_hold = '';
+%  if ( grep { $_ eq "provision_hold$svcpart" } $cgi->param ) {
+%    $provision_hold = $cgi->param("hidden_svc$svcpart");
+%  } else {
+%    $provision_hold = $pkg_svc->provision_hold;
+%  }
 %
 %  my @exports = $pkg_svc->part_svc->part_export;
 %  foreach my $export ( @exports ) {
@@ -72,6 +78,10 @@
       <INPUT TYPE="checkbox" NAME="no_bulk_skip<% $svcpart %>" VALUE="Y"<% $bulk_skip =~ /^Y/i ? '' : ' CHECKED' %>>
     </TD>
 
+    <TD ALIGN="center">
+      <INPUT TYPE="checkbox" NAME="provision_hold<% $svcpart %>" VALUE="Y"<% $provision_hold =~ /^Y/i ? ' CHECKED' : ''%>>
+    </TD>
+
   </TR>
 % foreach ( 1 .. $columns-1 ) {
 %       if ( $count == int( $_ * scalar(@part_svc) / $columns ) ) { 
@@ -127,6 +137,7 @@ my $thead =  "\n\n". ntable('#cccccc', 2).
              '<TH BGCOLOR="#dcdcdc">Service</TH>'.
              '<TH BGCOLOR="#dcdcdc"><FONT SIZE=-1>Hide<BR>from<BR>Invoices</FONT></TH>'.
              '<TH BGCOLOR="#dcdcdc"><FONT SIZE=-1>Bulk<BR>Charge</FONT></TH>'.
+             '<TH BGCOLOR="#dcdcdc"><FONT SIZE=-1>Hold<BR>Until<BR>Provision</FONT></TH>'.
              '</TR>';
 
 my $part_pkg = $opt{'object'};

-----------------------------------------------------------------------

Summary of changes:
 FS/FS/Schema.pm                      |    1 +
 FS/FS/cust_pkg.pm                    |   33 ++++++++++--------
 FS/FS/cust_svc.pm                    |   63 ++++++++++++++++++++++++++++++++++
 FS/FS/part_pkg.pm                    |   25 +++++++++-----
 FS/FS/pkg_svc.pm                     |    3 ++
 httemplate/edit/process/part_pkg.cgi |    2 ++
 httemplate/elements/tr-pkg_svc.html  |   11 ++++++
 7 files changed, 116 insertions(+), 22 deletions(-)




More information about the freeside-commits mailing list