finish at least the automatic provisioning part
authorivan <ivan>
Thu, 29 Jun 2006 13:47:44 +0000 (13:47 +0000)
committerivan <ivan>
Thu, 29 Jun 2006 13:47:44 +0000 (13:47 +0000)
FS/FS/inventory_class.pm
FS/FS/svc_Common.pm
httemplate/browse/inventory_class.html
httemplate/edit/part_svc.cgi
httemplate/edit/svc_acct.cgi
httemplate/edit/svc_broadband.cgi
httemplate/edit/svc_domain.cgi
httemplate/edit/svc_external.cgi
httemplate/edit/svc_forward.cgi
httemplate/edit/svc_www.cgi
httemplate/search/inventory_item.html

index 04ee207..508889b 100644 (file)
@@ -120,7 +120,7 @@ sub num_avail {
 
 sub num_sql {
   my( $self, $sql ) = @_;
-  my $sql = "AND $sql" if length($sql);
+  $sql = "AND $sql" if length($sql);
   my $statement =
     "SELECT COUNT(*) FROM inventory_item WHERE classnum = ? $sql";
   my $sth = dbh->prepare($statement) or die dbh->errstr. " preparing $statement";
index 962e36a..f2e1b9a 100644 (file)
@@ -9,10 +9,12 @@ use FS::cust_svc;
 use FS::part_svc;
 use FS::queue;
 use FS::cust_main;
+use FS::inventory_item;
+use FS::inventory_class;
 
 @ISA = qw( FS::cust_main_Mixin FS::Record );
 
-$DEBUG = 0;
+$DEBUG = 1;
 
 =head1 NAME
 
@@ -202,6 +204,12 @@ sub insert {
     $self->svcpart($cust_svc->svcpart);
   }
 
+  $error = $self->set_auto_inventory;
+  if ( $error ) {
+    $dbh->rollback if $oldAutoCommit;
+    return $error;
+  }
+
   $error = $self->SUPER::insert;
   if ( $error ) {
     $dbh->rollback if $oldAutoCommit;
@@ -297,7 +305,7 @@ sub delete {
   #new-style exports!
   unless ( $noexport_hack ) {
     foreach my $part_export ( $self->cust_svc->part_svc->part_export ) {
-      my $error = $part_export->export_delete($self);
+      $error = $part_export->export_delete($self);
       if ( $error ) {
         $dbh->rollback if $oldAutoCommit;
         return "exporting to ". $part_export->exporttype.
@@ -306,11 +314,18 @@ sub delete {
     }
   }
 
-  return $error if $error;
+  $error = $self->return_inventory;
+  if ( $error ) {
+    $dbh->rollback if $oldAutoCommit;
+    return "error returning inventory: $error";
+  }
 
   my $cust_svc = $self->cust_svc;
   $error = $cust_svc->delete;
-  return $error if $error;
+  if ( $error ) {
+    $dbh->rollback if $oldAutoCommit;
+    return $error;
+  }
 
   $dbh->commit or die $dbh->errstr if $oldAutoCommit;
 
@@ -338,7 +353,13 @@ sub replace {
   local $FS::UID::AutoCommit = 0;
   my $dbh = dbh;
 
-  my $error = $new->SUPER::replace($old);
+  my $error = $new->set_auto_inventory;
+  if ( $error ) {
+    $dbh->rollback if $oldAutoCommit;
+    return $error;
+  }
+
+  $error = $new->SUPER::replace($old);
   if ($error) {
     $dbh->rollback if $oldAutoCommit;
     return $error;
@@ -409,7 +430,7 @@ to test the return).  Usually called by the check method.
 
 sub setfixed {
   my $self = shift;
-  $self->setx('F');
+  $self->setx('F', @_);
 }
 
 =item setdefault
@@ -422,20 +443,68 @@ the FS::part_svc object (use ref() to test the return).
 
 sub setdefault {
   my $self = shift;
-  $self->setx('D');
+  $self->setx('D', @_ );
+}
+
+=item set_default_and_fixed
+
+=cut
+
+sub set_default_and_fixed {
+  my $self = shift;
+  $self->setx( [ 'D', 'F' ], @_ );
 }
 
+=item setx FLAG | FLAG_ARRAYREF , [ CALLBACK_HASHREF ]
+
+Sets fields according to the passed in flag or arrayref of flags.
+
+Optionally, a hashref of field names and callback coderefs can be passed.
+If a coderef exists for a given field name, instead of setting the field,
+the coderef is called with the column value (part_svc_column.columnvalue)
+as the single parameter.
+
+=cut
+
 sub setx {
   my $self = shift;
   my $x = shift;
+  my @x = ref($x) ? @$x : ($x);
+  my %coderef = @_ ? shift : {};
 
-  my $error;
-
-  $error =
+  my $error =
     $self->ut_numbern('svcnum')
   ;
   return $error if $error;
 
+  my $part_svc = $self->part_svc;
+  return "Unkonwn svcpart" unless $part_svc;
+
+  #set default/fixed/whatever fields from part_svc
+
+  foreach my $part_svc_column (
+    grep { my $f = $_->columnflag; grep { $f eq $_ } @x } #columnflag in @x
+    $part_svc->all_part_svc_column
+  ) {
+
+    my $columnname  = $part_svc_column->columnname;
+    my $columnvalue = $part_svc_column->columnvalue;
+
+    if ( exists( $coderef{columnname} ) ) {
+      &{ $coderef{$columnname} }( $self, $columnvalue);
+    } else {
+      $self->setfield( $columnname, $columnvalue );
+    }
+
+  }
+
+ $part_svc;
+
+}
+
+sub part_svc {
+  my $self = shift;
+
   #get part_svc
   my $svcpart;
   if ( $self->get('svcpart') ) {
@@ -445,20 +514,129 @@ sub setx {
     return "Unknown svcnum" unless $cust_svc; 
     $svcpart = $cust_svc->svcpart;
   }
-  my $part_svc = qsearchs( 'part_svc', { 'svcpart' => $svcpart } );
+
+  qsearchs( 'part_svc', { 'svcpart' => $svcpart } );
+
+}
+
+=item set_auto_inventory
+
+Sets any fields which auto-populate from inventory (see L<FS::part_svc>).
+If there is an error, returns the error, otherwise returns false.
+
+=cut
+
+sub set_auto_inventory {
+  my $self = shift;
+
+  my $error =
+    $self->ut_numbern('svcnum')
+  ;
+  return $error if $error;
+
+  my $part_svc = $self->part_svc;
   return "Unkonwn svcpart" unless $part_svc;
 
+  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;
+
   #set default/fixed/whatever fields from part_svc
   my $table = $self->table;
   foreach my $field ( grep { $_ ne 'svcnum' } $self->fields ) {
     my $part_svc_column = $part_svc->part_svc_column($field);
-    if ( $part_svc_column->columnflag eq $x ) {
-      $self->setfield( $field, $part_svc_column->columnvalue );
+    if ( $part_svc_column->columnflag eq 'A' && $self->$field() eq '' ) {
+
+      my $classnum = $part_svc_column->columnvalue;
+      my $inventory_item = qsearchs({
+        'table'     => 'inventory_item',
+        'hashref'   => { 'classnum' => $classnum, 
+                         'svcnum'   => '',
+                       },
+        'extra_sql' => 'LIMIT 1 FOR UPDATE',
+      });
+
+      unless ( $inventory_item ) {
+        $dbh->rollback if $oldAutoCommit;
+        my $inventory_class =
+          qsearchs('inventory_class', { 'classnum' => $classnum } );
+        return "Can't find inventory_class.classnum $classnum"
+          unless $inventory_class;
+        return "Out of ". $inventory_class->classname. "s\n"; #Lingua:: BS
+                                                              #for pluralizing
+      }
+
+      $inventory_item->svcnum( $self->svcnum );
+      my $ierror = $inventory_item->replace();
+      if ( $ierror ) {
+        $dbh->rollback if $oldAutoCommit;
+        return "Error provisioning inventory: $ierror";
+        
+      }
+
+      $self->setfield( $field, $inventory_item->item );
+
     }
   }
 
- $part_svc;
+ $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+
+ '';
+
+}
+
+=item return_inventory
+
+=cut
+
+sub return_inventory {
+  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;
+
+  foreach my $inventory_item ( $self->inventory_item ) {
+    $inventory_item->svcnum('');
+    my $error = $inventory_item->replace();
+    if ( $error ) {
+      $dbh->rollback if $oldAutoCommit;
+      return "Error returning inventory: $error";
+    }
+  }
+
+  $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+
+  '';
+}
+
+=item inventory_item
+
+Returns the inventory items associated with this svc_ record, as
+FS::inventory_item objects (see L<FS::inventory_item>.
+
+=cut
+
+sub inventory_item {
+  my $self = shift;
+  qsearch({
+    'table'     => 'inventory_item',
+    'hashref'   => { 'svcnum' => $self->svcnum, },
+  });
 }
 
 =item cust_svc
index 6da3c9e..4a15bf7 100644 (file)
@@ -8,7 +8,7 @@ tie my %labels, 'Tie::IxHash',
 
 my %link = (
   'num_avail' => ';avail=1',
-  'num_used'  => ';avail=1',
+  'num_used'  => ';used=1',
   'num_total' => '',
 );
 
index 77011e9..0298a54 100755 (executable)
@@ -179,9 +179,10 @@ my %defs = (
              'condition' =>
                sub { ref($_[0]) && $_[0]->{disable_fixed} }, 
            },
-    'M' => { 'desc' => 'Manual selection from inventory',
-             'condition' => $inv_sub,
-           },
+# need to template-ize httemplate/edit/svc_* first
+#    'M' => { 'desc' => 'Manual selection from inventory',
+#             'condition' => $inv_sub,
+#           },
     'A' => { 'desc' => 'Automatically fill in from inventory',
              'condition' => $inv_sub,
            },
index 1e87c67..4b324a5 100755 (executable)
@@ -68,18 +68,9 @@ unless ( $svcnum || $cgi->param('error') ) { #adding
     }
   }
 
-  #set fixed and default fields from part_svc
-  foreach my $part_svc_column (
-    grep { $_->columnflag } $part_svc->all_part_svc_column
-  ) {
-    if ( $part_svc_column->columnname eq 'usergroup' ) {
-      @groups = split(',', $part_svc_column->columnvalue);
-    } else {
-      $svc_acct->setfield( $part_svc_column->columnname,
-                           $part_svc_column->columnvalue,
-                         );
-    }
-  }
+  $svc_acct->set_default_and_fixed( {
+    'usergroup' => sub { @groups = split(',', shift ); },
+  } );
 
 }
 
@@ -274,7 +265,7 @@ if ( $part_svc->part_svc_column('popnum')->columnflag eq 'F' ) {
 <% foreach my $xid (qw( uid gid )) { %>
 
   <%
-  if ( $part_svc->part_svc_column($xid)->columnflag eq 'F'
+  if ( $part_svc->part_svc_column($xid)->columnflag =~ /^[FA]$/
        || ! $conf->exists("svc_acct-edit_$xid")
      ) {
   %>
@@ -376,7 +367,7 @@ if ( $part_svc->part_svc_column('shell')->columnflag eq 'F'
 <% } %>
 
 
-<% if ( $part_svc->part_svc_column('slipip')->columnflag eq 'F' ) { %>
+<% if ( $part_svc->part_svc_column('slipip')->columnflag =~ /^[FA]$/ ) { %>
 
   <INPUT TYPE="hidden" NAME="slipip" VALUE="<%= $svc_acct->slipip %>">
 
@@ -396,7 +387,7 @@ foreach my $r ( grep { /^r(adius|[cr])_/ } fields('svc_acct') ) {
   my $a = $2;
 %>
 
-  <% if ( $part_svc->part_svc_column($r)->columnflag eq 'F' ) { %>
+  <% if ( $part_svc->part_svc_column($r)->columnflag =~ /^[FA]$/ ) { %>
 
     <INPUT TYPE="hidden" NAME="<%= $r %>" VALUE="<%= $svc_acct->getfield($r) %>">
 
index cbd0c2c..d66cff6 100644 (file)
@@ -47,14 +47,7 @@ if ( $cgi->param('error') ) {
 
     $svcnum='';
 
-    #set fixed and default fields from part_svc
-    foreach my $part_svc_column (
-      grep { $_->columnflag } $part_svc->all_part_svc_column
-    ) {
-      $svc_broadband->setfield( $part_svc_column->columnname,
-                                $part_svc_column->columnvalue,
-                              );
-    }
+    $svc_broadband->set_default_and_fixed;
 
   }
 }
index f47ba0a..1156bf0 100755 (executable)
@@ -44,14 +44,7 @@ if ( $cgi->param('error') ) {
 
     $svcnum='';
 
-    #set fixed and default fields from part_svc
-    foreach my $part_svc_column (
-      grep { $_->columnflag } $part_svc->all_part_svc_column
-    ) {
-      $svc_domain->setfield( $part_svc_column->columnname,
-                             $part_svc_column->columnvalue,
-                           );
-    }
+    $svc_domain->set_default_and_fixed;
 
   }
 
index bcfc85e..38b3ce1 100644 (file)
@@ -40,14 +40,7 @@ if ( $cgi->param('error') ) {
 
     $svcnum='';
 
-    #set fixed and default fields from part_svc
-    foreach my $part_svc_column (
-      grep { $_->columnflag } $part_svc->all_part_svc_column
-    ) {
-      $svc_external->setfield( $part_svc_column->columnname,
-                               $part_svc_column->columnvalue,
-                             );
-    }
+    $svc_external->set_default_and_fixed;
 
   }
 }
index c1b90a9..c32fbd7 100755 (executable)
@@ -44,14 +44,7 @@ if ( $cgi->param('error') ) {
 
     $svcnum='';
 
-    #set fixed and default fields from part_svc
-    foreach my $part_svc_column (
-      grep { $_->columnflag } $part_svc->all_part_svc_column
-    ) {
-      $svc_forward->setfield( $part_svc_column->columnname,
-                              $part_svc_column->columnvalue,
-                            );
-    }
+    $svc_forward->set_default_and_fixed;
   }
 
 }
index 3cb7528..280346b 100644 (file)
@@ -42,14 +42,7 @@ if ( $cgi->param('error') ) {
 
     $svcnum='';
 
-    #set fixed and default fields from part_svc
-    foreach my $part_svc_column (
-      grep { $_->columnflag } $part_svc->all_part_svc_column
-    ) {
-      $svc_www->setfield( $part_svc_column->columnname,
-                          $part_svc_column->columnvalue,
-                        );
-    }
+    $svc_www->set_default_and_fixed;
 
   }
 }
index bd74f56..7049c88 100644 (file)
@@ -24,7 +24,30 @@ if ( $cgi->param('avail') ) {
 my $count_query =
   "SELECT COUNT(*) FROM inventory_item WHERE classnum = $classnum $extra_sql";
 
+my $link = sub {
+  my $inventory_item = shift;
+  if ( $inventory_item->svcnum ) {
+    [ "${p}view/svc_acct.cgi?", 'svcnum' ];
+  } else {
+    '';
+  }
+};
+my $link_cust = sub {
+  my $inventory_item = shift;
+  if ( $inventory_item->custnum ) {
+    [ "${p}view/cust_main.cgi?", 'custnum' ];
+  } else {
+    '';
+  }
+};
+
+my $addl_from = ' LEFT JOIN cust_svc  USING ( svcnum  ) '.
+                ' LEFT JOIN part_svc  USING ( svcpart ) '.
+                ' LEFT JOIN cust_pkg  USING ( pkgnum  ) '.
+                ' LEFT JOIN cust_main USING ( custnum ) ';
+
 %><%= include( 'elements/search.html',
+
                  'title'       => $title,
 
                  #less lame to use Lingua:: something to pluralize
@@ -33,19 +56,52 @@ my $count_query =
                  'query'       => {
                                     'table'   => 'inventory_item',
                                     'hashref' => { 'classnum' => $classnum },
+                                    'select'  => join(', ',
+                                        'inventory_item.*',
+                                        'cust_main.custnum',
+                                        FS::UI::Web::cust_sql_fields(),
+                                      ),
                                     'extra_sql' => $extra_sql,
+                                    'addl_from' => $addl_from,
                                   },
 
                  'count_query' => $count_query,
 
-                 # XXX proper full service/customer link ala svc_acct
-                 'header'      => [ '#', $inventory_class->classname, 'svcnum' ],
+                 'header'      => [
+                   '#',
+                   $inventory_class->classname,
+                   'Service',
+                   FS::UI::Web::cust_header(),
+                 ],
 
                  'fields'      => [
                    'itemnum',
                    'item',
-                   'svcnum', #XXX proper full service customer link ala svc_acct
+                   #'svcnum', #XXX proper full service customer link ala svc_acct
                              # "unallocated" ?  "available" ?
+                   sub {
+                     #this could be way more efficient with a mixin
+                     # like cust_main_Mixin that let us all all the methods
+                     # on data we already have...
+                     my $inventory_item = shift;
+                     my $cust_svc = $inventory_item->cust_svc;
+                     if ( $cust_svc ) {
+                       my($label, $value) = $cust_svc->label;
+                       "$label: $value";
+                     } else {
+                       '(available)';
+                     }
+                   },
+
+                   \&FS::UI::Web::cust_fields,
+
+                 ],
+
+                 'links'       => [
+                   '',
+                   '',
+                   $link,
+                   ( map { $link_cust } FS::UI::Web::cust_header() ),
                  ],
 
              )