Add an option to the web interface to batch upload new entries to the
authorivan <ivan>
Wed, 8 Mar 2006 12:14:04 +0000 (12:14 +0000)
committerivan <ivan>
Wed, 8 Mar 2006 12:14:04 +0000 (12:14 +0000)
inventory_item table.

FS/FS/inventory_item.pm
httemplate/misc/inventory_item-import.html [new file with mode: 0644]
httemplate/misc/process/inventory_item-import.html [new file with mode: 0644]
httemplate/search/inventory_class.html
httemplate/search/inventory_item.html

index 5312d95..23bacf0 100644 (file)
@@ -2,8 +2,9 @@ package FS::inventory_item;
 
 use strict;
 use vars qw( @ISA );
-use FS::Record qw( qsearch qsearchs );
+use FS::Record qw( dbh qsearch qsearchs );
 use FS::inventory_class;
+use FS::cust_svc;
 
 @ISA = qw(FS::Record);
 
@@ -105,20 +106,96 @@ sub check {
     $self->ut_numbern('itemnum')
     || $self->ut_foreign_key('classnum', 'inventory_class', 'classnum' )
     || $self->ut_text('item')
-    || $self->ut_numbern('svcnum')
+    || $self->ut_foreign_keyn('svcnum', 'cust_svc', 'svcnum' )
   ;
   return $error if $error;
 
   $self->SUPER::check;
 }
 
+=item cust_svc
+
+Returns the customer service associated with this inventory item, if the
+item has been used (see L<FS::cust_svc>).
+
+=cut
+
+sub cust_svc {
+  my $self = shift;
+  return '' unless $self->svcnum;
+  qsearchs( 'cust_svc', { 'svcnum' => $self->svcnum } );
+}
+
+=back
+
+=head1 CLASS METHODS
+
+=over 4
+
+=item batch_import
+
+=cut
+
+sub batch_import {
+  my $param = shift;
+
+  my $fh = $param->{filehandle};
+
+  my $imported = 0;
+
+  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 $line;
+  while ( defined($line=<$fh>) ) {
+
+    chomp $line;
+
+    my $inventory_item = new FS::inventory_item {
+      'classnum' => $param->{'classnum'},
+      'item'     => $line,
+    };
+
+    my $error = $inventory_item->insert;
+
+    if ( $error ) {
+      $dbh->rollback if $oldAutoCommit;
+      return $error;
+
+      #or just skip?
+      #next;
+    }
+
+    $imported++;
+  }
+
+  $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+
+  #might want to disable this if we skip records for any reason...
+  return "Empty file!" unless $imported;
+
+  '';
+
+}
+
 =back
 
 =head1 BUGS
 
+maybe batch_import should be a regular method in FS::inventory_class
+
 =head1 SEE ALSO
 
-L<FS::Record>, schema.html from the base documentation.
+L<inventory_class>, L<cust_svc>, L<FS::Record>, schema.html from the base
+documentation.
 
 =cut
 
diff --git a/httemplate/misc/inventory_item-import.html b/httemplate/misc/inventory_item-import.html
new file mode 100644 (file)
index 0000000..a702fbc
--- /dev/null
@@ -0,0 +1,20 @@
+<%
+
+my $classnum = $cgi->param('classnum');
+$classnum =~ /^(\d+)$/ or eidiot "illegal classnum $classnum";
+$classnum = $1;
+my $inventory_class = qsearchs('inventory_class', { 'classnum' => $classnum } );
+
+%><%= include("/elements/header.html", $inventory_class->classname. 's') %>
+
+<FORM ACTION="process/inventory_item-import.html" METHOD="POST" ENCTYPE="multipart/form-data">
+<INPUT TYPE="hidden" NAME="classnum" VALUE="<%= $classnum %>">
+Import a file containing <%= $inventory_class->classname %>s, one per line.<BR><BR>
+
+Filename: <INPUT TYPE="file" NAME="filename"><BR><BR>
+
+<INPUT TYPE="submit" VALUE="Upload">
+</FORM>
+
+<%= include('/elements/footer.html') %>
+
diff --git a/httemplate/misc/process/inventory_item-import.html b/httemplate/misc/process/inventory_item-import.html
new file mode 100644 (file)
index 0000000..8a58203
--- /dev/null
@@ -0,0 +1,27 @@
+<%
+
+  my $fh = $cgi->upload('filename');
+
+  my $error = defined($fh)
+    ? FS::inventory_item::batch_import( {
+        'filehandle' => $fh,
+        'classnum'   => $cgi->param('classnum'),
+      } )
+    : 'No file';
+
+  if ( $error ) {
+    %>
+    <!-- mason kludge -->
+    <%
+    eidiot($error);
+#    $cgi->param('error', $error);
+#    print $cgi->redirect( "${p}cust_main-import.cgi
+  } else {
+    %>
+    <!-- mason kludge -->
+    <%= include("/elements/header.html",'Import sucessful') %>
+    <!-- XXX redirect to batch search like the payment entry... -->
+    <%= include("/elements/footer.html",'Import sucessful') %> <%
+  }
+%>
+
index 1bf1bcb..37735f3 100644 (file)
@@ -5,11 +5,18 @@ tie my %labels, 'Tie::IxHash',
   'num_used'  => 'In use', #'Used', #'Allocated',
   'num_total' => 'Total',
 ;
-my %inv_action_link = (
-  'num_avail' => 'eventually'
+
+my %link = (
+  'num_avail' => ';avail=1',
+  'num_used'  => ';avail=1',
+  'num_total' => '',
 );
-my %inv_action_label = (
-  'num_avail' => 'upload_batch'
+
+my %inv_action_link = (
+  'num_avail' => [ 'upload batch',
+                   $p.'misc/inventory_item-import.html?classnum=',
+                   'classnum'
+                 ],
 );
 
 my $link = [ "${p}edit/inventory_class.html?", 'classnum' ];
@@ -29,20 +36,44 @@ my $link = [ "${p}edit/inventory_class.html?", 'classnum' ];
                                           #my $inventory_class = shift;
                                           my $i_c = shift;
 
+                                          my $link =
+                                            $p. 'search/inventory_item.html?'.
+                                            'classnum='. $i_c->classnum;
+
+                                          my %actioncol = ();
+                                          foreach ( keys %inv_action_link ) {
+                                            my($label, $baseurl, $method) =
+                                              @{ $inv_action_link{$_} };
+                                            my $url = $baseurl. $i_c->$method();
+                                            $actioncol{$_} =
+                                              '<FONT SIZE="-1">'.
+                                              '('.
+                                              '<A HREF="'.$url.'">'.
+                                              $label.
+                                              '</A>'.
+                                              ')'.
+                                              '</FONT>';
+                                          }
+
+                                          my %num = map { 
+                                            $_ => $i_c->$_();
+                                          } keys %labels;
+
                                           [ map {
                                                   [
                                                     {
-                                                      'data'  => '<B>'. $i_c->$_(). '</B>',
+                                                      'data'  => '<B>'. $num{$_}. '</B>',
                                                       'align' => 'right',
                                                     },
                                                     {
                                                       'data'  => $labels{$_},
                                                       'align' => 'left',
-                                                    },
-                                                    { 'data'  => ( exists($inv_action_link{$_})
-                                                                   ? '<FONT SIZE="-1">(<A HREF="'. $inv_action_link{$_}. '">'. $inv_action_label{$_}. '</A>)</FONT>'
-                                                                   : ''
+                                                      'link'  => ( $num{$_}
+                                                                     ? $link.$link{$_}
+                                                                     : ''
                                                                  ),
+                                                    },
+                                                    { 'data'  => $actioncol{$_},
                                                       'align'  => 'left',
                                                     },
                                                   ]
index ff7f1fa..bd74f56 100644 (file)
@@ -1,15 +1,31 @@
 <%
 
 my $classnum = $cgi->param('classnum');
-$classnum =~ /^(\d+)$/ or eidiot "illegal agentnum $agentnum";
+$classnum =~ /^(\d+)$/ or eidiot "illegal classnum $classnum";
 $classnum = $1;
-my $inventory_class = qsearchs('inventory_class', { 'classnum' => $classnum } );
+
+my $inventory_class = qsearchs( {
+  'table'     => 'inventory_class',
+  'hashref'   => { 'classnum' => $classnum },
+} );
+
+my $title = $inventory_class->classname. ' Inventory';
+
+#little false laziness with SQL fragments in inventory_class.pm
+my $extra_sql = '';
+if ( $cgi->param('avail') ) {
+  $extra_sql = 'AND ( svcnum IS NULL OR svcnum = 0 )';
+  $title .= ' - Available';
+} elsif ( $cgi->param('used') ) {
+  $extra_sql = 'AND svcnum IS NOT NULL AND svcnum > 0';
+  $title .= ' - In use';
+}
 
 my $count_query =
-  "SELECT COUNT(*) FROM inventory_class WHERE classnum = $classnum";
+  "SELECT COUNT(*) FROM inventory_item WHERE classnum = $classnum $extra_sql";
 
 %><%= include( 'elements/search.html',
-                 'title'       => $inventory_class->classname. ' Inventory',
+                 'title'       => $title,
 
                  #less lame to use Lingua:: something to pluralize
                  'name'        => $inventory_class->classname. 's',
@@ -17,6 +33,7 @@ my $count_query =
                  'query'       => {
                                     'table'   => 'inventory_item',
                                     'hashref' => { 'classnum' => $classnum },
+                                    'extra_sql' => $extra_sql,
                                   },
 
                  'count_query' => $count_query,