populate MAC address from inventory for svc_phone devices, RT7794
authorlevinse <levinse>
Sat, 22 Jan 2011 20:03:52 +0000 (20:03 +0000)
committerlevinse <levinse>
Sat, 22 Jan 2011 20:03:52 +0000 (20:03 +0000)
FS/FS/Schema.pm
FS/FS/part_device.pm
httemplate/browse/part_device.html
httemplate/edit/part_device.html
httemplate/edit/phone_device.html
httemplate/elements/select-mac.html [new file with mode: 0644]
httemplate/elements/tr-select-mac.html [new file with mode: 0644]
httemplate/misc/macinventory.cgi [new file with mode: 0644]

index 1e773a7..ce1cd4f 100644 (file)
@@ -2810,7 +2810,7 @@ sub tables_hashref {
       'columns' => [
         'devicepart', 'serial',  '',      '', '', '',
         'devicename', 'varchar', '', $char_d, '', '',
-        #'classnum', #tie to an inventory class?
+        'inventory_classnum', 'int', 'NULL', '', '', '',
       ],
       'primary_key' => 'devicepart',
       'unique' => [ [ 'devicename' ] ], #?
index 4963584..0f840a7 100644 (file)
@@ -40,6 +40,7 @@ primary key
 
 devicename
 
+=item inventory_classnum
 
 =back
 
@@ -103,6 +104,7 @@ sub check {
   my $error = 
     $self->ut_numbern('devicepart')
     || $self->ut_text('devicename')
+    || $self->ut_foreign_keyn('inventory_classnum', 'inventory_class', 'classnum')
   ;
   return $error if $error;
 
@@ -121,6 +123,19 @@ sub part_export {
     qsearch( 'export_device', { 'devicepart' => $self->devicepart } );
 }
 
+=item inventory_class
+
+Returns the inventory class (see L<FS::inventory_class>) for this device, 
+if any.
+
+=cut
+
+sub inventory_class {
+  my $self = shift;
+  return '' unless $self->inventory_classnum;
+  qsearchs('inventory_class', { 'classnum' => $self->inventory_classnum });
+}
+
 sub process_batch_import {
   my $job = shift;
 
index 5c8fde3..69387dd 100644 (file)
@@ -8,12 +8,20 @@
                                   ],
                  'query'       => { 'table' => 'part_device', },
                  'count_query' => 'SELECT COUNT(*) FROM part_device',
-                 'header'      => [ '#', 'Device type' ],
+                 'header'      => [ '#', 'Device type', 'Inventory Class', ],
                  'fields'      => [ 'devicepart',
                                     'devicename',
+                                   sub {
+                                       my $part_device = shift;
+                                       my $inventory_class = $part_device->inventory_class;
+                                       return $inventory_class->classname 
+                                           if $inventory_class;
+                                       '';
+                                   },
                                   ],
                  'links'       => [ $link,
                                     $link,
+                                   '',
                                   ],
              )
 %>
index 146070f..1317c8d 100644 (file)
@@ -4,7 +4,9 @@
                  'labels' => { 
                                'devicepart' => 'Part number',
                                'devicename' => 'Device name',
+                              'inventory_classnum' => 'Inventory class',
                              },
+                'fields' => \@fields,
                  'viewall_dir' => 'browse',
                  'html_bottom' => $html_bottom_sub,
            )
@@ -20,6 +22,24 @@ my $extra_sql =
       );
 $extra_sql = $extra_sql ? " WHERE ( $extra_sql ) " : " WHERE 0 = 1 ";
 
+my @inventory_classnums;
+push @inventory_classnums, '';
+my %inventory_classnum_labels;
+$inventory_classnum_labels{''} = '';
+my @inventory_classes = qsearch('inventory_class', {} );
+foreach my $inventory_class ( @inventory_classes ) {
+    push @inventory_classnums, $inventory_class->classnum;
+    $inventory_classnum_labels{$inventory_class->classnum} = $inventory_class->classname;
+}
+                       
+my @fields;
+push @fields, 'devicename',
+             { field => 'inventory_classnum', 
+               type => 'select',
+               options => \@inventory_classnums,
+               labels => \%inventory_classnum_labels,
+             };
+
 my $html_bottom_sub = sub {
   my $part_device = shift;
 
index a1aa166..c42e714 100644 (file)
                                  'type'     => 'select-table',
                                  'table'    => 'part_device',
                                  'name_col' => 'devicename',
+                                'onchange' => 'devicepart_changed',
                                  'empty_label' =>'Select device type',
                                  #'hashref'        =>{ disabled => '' },
                                },
-                               'mac_addr',
+                              { field => 'mac_addr',
+                                type => 'select-mac',
+                              },
                                { 'field' => 'svcnum',
                                  'type'  => 'hidden',
                                },
                                      my( $cgi, $object ) = @_;
                                      $object->svcnum( $cgi->param('svcnum') );
                                    },
+                'html_foot' => $html_foot,
            )
 %>
 <%init>
 
+my @deviceparts_with_inventory;
+my @part_device = qsearch('part_device', {} );
+foreach my $part_device ( @part_device ) {
+    push @deviceparts_with_inventory, $part_device->devicepart
+       if $part_device->inventory_classnum;
+}
+
+my $html_foot = sub {
+    my $js = "
+<SCRIPT TYPE=\"text/javascript\">
+
+  function opt(what,value,text) {
+    var optionName = new Option(text, value, false, false);
+    var length = what.length;
+    what.options[length] = optionName;
+  }
+
+    function devicepart_changed(what){
+       
+       var macsel = document.getElementById('sel_mac_addr');
+       var mac = document.getElementById('mac_addr');
+       
+       function update_macs(macs) {
+           for ( var i = macsel.length; i >= 0; i-- )
+             macsel.options[i] = null;
+           
+           var macArray = eval('(' + macs + ')' );
+           if(macArray.length == 0) 
+               opt(macsel,'','No MAC addresses found in inventory for this device type');
+           else
+               opt(macsel,'','Select MAC address');
+
+           for ( var i = 0; i < macArray.length; i++ ) {
+               opt(macsel,macArray[i],macArray[i]);
+           }
+
+       }
+
+       var devicepart = what.options[what.selectedIndex].value;
+
+       var deviceparts_with_inventory = new Array(\"";
+$js .= join("\",\"",@deviceparts_with_inventory);
+$js .= "\");
+
+       var hasInventory = false;
+       for ( i = 0; i < deviceparts_with_inventory.length; i++ ) {
+           if ( deviceparts_with_inventory[i] == devicepart ) 
+               hasInventory = true;
+       }
+       
+
+       if(hasInventory) { // do the AJAX thing, disable text field
+           macsel.style.display = 'inline';
+           mac.style.display = 'none';
+           mac.value = '';
+           get_macs( devicepart, update_macs );
+       } else { // clear & display text field only, clear/hide select
+           mac.style.display = 'inline';
+           macsel.style.display = 'none';
+           macsel.selectedIndex = 0;
+       }
+
+    }
+</SCRIPT>";
+
+  $js;
+};
+
 # :/  needs agent-virt so you can't futz with arbitrary devices
 
 die "access denied"
diff --git a/httemplate/elements/select-mac.html b/httemplate/elements/select-mac.html
new file mode 100644 (file)
index 0000000..3153ca7
--- /dev/null
@@ -0,0 +1,19 @@
+<% include('/elements/xmlhttp.html',
+              'url'  => $p.'misc/macinventory.cgi',
+              'subs' => [ $opt{'prefix'}. 'get_macs' ],
+          )
+%>
+
+<% include( '/elements/input-text.html', %opt, 'type'=>'text' ) %>
+
+<SELECT ID="<% $opt{'prefix'} %>sel_mac_addr" NAME="<% $opt{'prefix'} %>mac_addr" 
+    notonChange="<% $opt{'prefix'} %>mac_addr_changed(this); <% $opt{'onchange'} %>"
+    <% $opt{'disabled'} %> STYLE="display: none">
+  <OPTION VALUE="">Select MAC address</OPTION>
+</SELECT>
+
+<%init>
+
+my %opt = @_;
+
+</%init>
diff --git a/httemplate/elements/tr-select-mac.html b/httemplate/elements/tr-select-mac.html
new file mode 100644 (file)
index 0000000..026923b
--- /dev/null
@@ -0,0 +1,12 @@
+<% include('tr-td-label.html', @_ ) %>
+ <TD>
+      <% include('/elements/select-mac.html', %opt ) %>
+ </TD>
+</TR>
+
+<%init>
+
+my %opt = @_;
+
+</%init>
+
diff --git a/httemplate/misc/macinventory.cgi b/httemplate/misc/macinventory.cgi
new file mode 100644 (file)
index 0000000..b07da97
--- /dev/null
@@ -0,0 +1,25 @@
+<% objToJson(\@macs) %>
+<%init>
+
+# XXX: this should be agent-virtualized / limited
+
+my $devicepart = $cgi->param('arg');
+
+die 'invalid devicepart' unless $devicepart =~ /^\d+$/;
+
+my $part_device = qsearchs('part_device', { 'devicepart' => $devicepart } );
+die "unknown devicepart $devicepart" unless $part_device;
+
+my $inventory_class = $part_device->inventory_class;
+die "devicepart $devicepart has no inventory" unless $inventory_class;
+
+my @inventory_item =
+    qsearch('inventory_item', { 'classnum' => $inventory_class->classnum } );
+
+my @macs;
+
+foreach my $inventory_item ( @inventory_item ) {
+    push @macs, $inventory_item->item;
+}
+
+</%init>