bulk DID orders and inventory, RT11291
authorlevinse <levinse>
Sun, 13 Feb 2011 07:23:42 +0000 (07:23 +0000)
committerlevinse <levinse>
Sun, 13 Feb 2011 07:23:42 +0000 (07:23 +0000)
23 files changed:
FS/FS.pm
FS/FS/Mason.pm
FS/FS/Record.pm
FS/FS/Schema.pm
FS/FS/did_order.pm [new file with mode: 0644]
FS/FS/did_vendor.pm [new file with mode: 0644]
FS/FS/lata.pm [new file with mode: 0644]
FS/FS/phone_avail.pm
FS/MANIFEST
FS/bin/freeside-lata-import [new file with mode: 0755]
FS/t/did_order.t [new file with mode: 0644]
FS/t/did_vendor.t [new file with mode: 0644]
FS/t/lata.t [new file with mode: 0644]
httemplate/browse/did_order.html [new file with mode: 0644]
httemplate/browse/did_vendor.html [new file with mode: 0644]
httemplate/edit/did_order.html [new file with mode: 0644]
httemplate/edit/did_vendor.html [new file with mode: 0644]
httemplate/edit/elements/edit.html
httemplate/edit/process/did_order.html [new file with mode: 0644]
httemplate/edit/process/did_vendor.html [new file with mode: 0644]
httemplate/elements/menu.html
httemplate/elements/tr-select-state.html [new file with mode: 0644]
httemplate/misc/phone_avail-import.html

index af35d96..db26204 100644 (file)
--- a/FS/FS.pm
+++ b/FS/FS.pm
@@ -162,6 +162,12 @@ L<FS::part_device> - Device definition class
 
 L<FS::phone_avail> - Phone number availability cache
 
+L<FS::lata> - LATA number to name mapping class
+
+L<FS::did_vendor> - Bulk DID order vendor class
+
+L<FS::did_order> - Bulk DID order class
+
 L<FS::cdr> - Call Detail Record class
 
 L<FS::cdr_batch> - Call Detail Record batch class
index b66dc8c..53b9861 100644 (file)
@@ -259,6 +259,9 @@ if ( -e $addl_handler_use_file ) {
   use FS::part_pkg_discount;
   use FS::svc_cert;
   use FS::cust_note_class;
+  use FS::lata;
+  use FS::did_vendor;
+  use FS::did_order;
   # Sammath Naur
 
   if ( $FS::Mason::addl_handler_use ) {
index 2e2612e..33a3609 100644 (file)
@@ -1591,6 +1591,7 @@ sub process_batch_import {
     params                     => { map { $_ => $param->{$_} } @pass_params },
     #?
     default_csv                => $opt->{default_csv},
+    postinsert_callback        => $opt->{postinsert_callback},
   );
 
   if ( $opt->{'batch_namecol'} ) {
@@ -1664,6 +1665,8 @@ sub batch_import {
   my( $type, $header, $sep_char, $fixedlength_format, 
       $xml_format, $row_callback, @fields );
   my $postinsert_callback = '';
+  $postinsert_callback = $param->{'postinsert_callback'}
+         if $param->{'postinsert_callback'};
   if ( $param->{'format'} ) {
 
     my $format  = $param->{'format'};
@@ -1709,9 +1712,6 @@ sub batch_import {
     $row_callback = '';
     @fields = @{ $param->{'fields'} };
 
-    $postinsert_callback = $param->{'postinsert_callback'}
-      if $param->{'postinsert_callback'}
-
   } else {
     die "neither format nor fields specified";
   }
index a7f0bfa..42153bf 100644 (file)
@@ -2839,6 +2839,8 @@ sub tables_hashref {
         'nxx',         'char',    'NULL',       3, '', '', 
         'station',     'char',    'NULL',       4, '', '',
         'name',        'varchar', 'NULL', $char_d, '', '',
+        'rate_center_abbrev', 'varchar', 'NULL', $char_d, '', '',
+        'ordernum',      'int',     'NULL',      '', '', '',
         'svcnum',      'int',     'NULL',      '', '', '',
         'availbatch', 'varchar',  'NULL', $char_d, '', '',
       ],
@@ -2852,6 +2854,45 @@ sub tables_hashref {
                     [ 'availbatch' ],
                   ],
     },
+    
+    'lata' => {
+      'columns' => [
+        'latanum',    'int',      '',      '', '', '', 
+        'description',   'varchar',    '',      $char_d, '', '', 
+      ],
+      'primary_key' => 'latanum',
+      'unique' => [],
+      'index'  => [],
+    },
+    
+    'did_vendor' => {
+      'columns' => [
+        'vendornum',    'serial',      '',      '', '', '', 
+        'vendorname',   'varchar',        '',     $char_d, '', '', 
+      ],
+      'primary_key' => 'vendornum',
+      'unique' => [],
+      'index'  => [],
+    },
+    
+    'did_order' => {
+      'columns' => [
+        'ordernum',    'serial',      '',      '', '', '', 
+        'vendornum',   'int',       '',      '', '', '', 
+        'vendor_order_id',   'varchar',  '',   $char_d, '', '', 
+        'msa',        'varchar', 'NULL', $char_d, '', '',
+        'latanum',      'int',     'NULL',      '', '', '',
+        'rate_center',        'varchar', 'NULL', $char_d, '', '',
+        'state',       'char',    'NULL',       2, '', '', 
+        'quantity',      'int',     '',      '', '', '',
+        'submitted',      'int',     '',      '', '', '',
+        'confirmed',      'int',     'NULL',      '', '', '',
+        'received',      'int',     'NULL',      '', '', '',
+      ],
+      'primary_key' => 'ordernum',
+      'unique' => [ [ 'vendornum', 'vendor_order_id' ] ],
+      'index'  => [],
+    },
 
     'reason_type' => {
       'columns' => [
diff --git a/FS/FS/did_order.pm b/FS/FS/did_order.pm
new file mode 100644 (file)
index 0000000..6b199a9
--- /dev/null
@@ -0,0 +1,166 @@
+package FS::did_order;
+
+use strict;
+use base qw( FS::Record );
+use FS::Record qw( qsearch qsearchs );
+
+=head1 NAME
+
+FS::did_order - Object methods for did_order records
+
+=head1 SYNOPSIS
+
+  use FS::did_order;
+
+  $record = new FS::did_order \%hash;
+  $record = new FS::did_order { 'column' => 'value' };
+
+  $error = $record->insert;
+
+  $error = $new_record->replace($old_record);
+
+  $error = $record->delete;
+
+  $error = $record->check;
+
+=head1 DESCRIPTION
+
+An FS::did_order object represents a bulk DID order.  FS::did_order inherits from
+FS::Record.  The following fields are currently supported:
+
+=over 4
+
+=item ordernum
+
+primary key
+
+=item vendornum
+
+vendornum
+
+=item vendor_order_id
+
+vendor_order_id
+
+=item msa
+
+msa
+
+=item latanum
+
+latanum
+
+=item rate_center
+
+rate_center
+
+=item state
+
+state
+
+=item quantity
+
+quantity
+
+=item submitted
+
+submitted
+
+=item confirmed
+
+confirmed
+
+=item received
+
+received
+
+
+=back
+
+=head1 METHODS
+
+=over 4
+
+=item new HASHREF
+
+Creates a new bulk DID order.  To add it to the database, see L<"insert">.
+
+Note that this stores the hash reference, not a distinct copy of the hash it
+points to.  You can ask the object for a copy with the I<hash> method.
+
+=cut
+
+# the new method can be inherited from FS::Record, if a table method is defined
+
+sub table { 'did_order'; }
+
+=item insert
+
+Adds this record to the database.  If there is an error, returns the error,
+otherwise returns false.
+
+=cut
+
+# the insert method can be inherited from FS::Record
+
+=item delete
+
+Delete this record from the database.
+
+=cut
+
+# the delete method can be inherited from FS::Record
+
+=item replace OLD_RECORD
+
+Replaces the OLD_RECORD with this one in the database.  If there is an error,
+returns the error, otherwise returns false.
+
+=cut
+
+# the replace method can be inherited from FS::Record
+
+=item check
+
+Checks all fields to make sure this is a valid bulk DID order.  If there is
+an error, returns the error, otherwise returns false.  Called by the insert
+and replace methods.
+
+=cut
+
+# the check method should currently be supplied - FS::Record contains some
+# data checking routines
+
+sub check {
+  my $self = shift;
+
+  my $error = 
+    $self->ut_numbern('ordernum')
+    || $self->ut_foreign_key('vendornum', 'did_vendor', 'vendornum' )
+    || $self->ut_text('vendor_order_id')
+    || $self->ut_textn('msa')
+    || $self->ut_foreign_keyn('latanum', 'lata', 'latanum')
+    || $self->ut_textn('rate_center')
+    || $self->ut_textn('state')
+    || $self->ut_number('quantity')
+    || $self->ut_number('submitted')
+    || $self->ut_numbern('confirmed')
+    || $self->ut_numbern('received')
+  ;
+  return $error if $error;
+
+  $self->SUPER::check;
+}
+
+=back
+
+=head1 BUGS
+
+=head1 SEE ALSO
+
+L<FS::Record>, schema.html from the base documentation.
+
+=cut
+
+1;
+
diff --git a/FS/FS/did_vendor.pm b/FS/FS/did_vendor.pm
new file mode 100644 (file)
index 0000000..a108435
--- /dev/null
@@ -0,0 +1,121 @@
+package FS::did_vendor;
+
+use strict;
+use base qw( FS::Record );
+use FS::Record qw( qsearch qsearchs );
+
+=head1 NAME
+
+FS::did_vendor - Object methods for did_vendor records
+
+=head1 SYNOPSIS
+
+  use FS::did_vendor;
+
+  $record = new FS::did_vendor \%hash;
+  $record = new FS::did_vendor { 'column' => 'value' };
+
+  $error = $record->insert;
+
+  $error = $new_record->replace($old_record);
+
+  $error = $record->delete;
+
+  $error = $record->check;
+
+=head1 DESCRIPTION
+
+An FS::did_vendor object represents a bulk DID vendor.  FS::did_vendor inherits from
+FS::Record.  The following fields are currently supported:
+
+=over 4
+
+=item vendornum
+
+primary key
+
+=item vendorname
+
+vendorname
+
+
+=back
+
+=head1 METHODS
+
+=over 4
+
+=item new HASHREF
+
+Creates a new bulk DID vendor.  To add it to the database, see L<"insert">.
+
+Note that this stores the hash reference, not a distinct copy of the hash it
+points to.  You can ask the object for a copy with the I<hash> method.
+
+=cut
+
+# the new method can be inherited from FS::Record, if a table method is defined
+
+sub table { 'did_vendor'; }
+
+=item insert
+
+Adds this record to the database.  If there is an error, returns the error,
+otherwise returns false.
+
+=cut
+
+# the insert method can be inherited from FS::Record
+
+=item delete
+
+Delete this record from the database.
+
+=cut
+
+# the delete method can be inherited from FS::Record
+
+=item replace OLD_RECORD
+
+Replaces the OLD_RECORD with this one in the database.  If there is an error,
+returns the error, otherwise returns false.
+
+=cut
+
+# the replace method can be inherited from FS::Record
+
+=item check
+
+Checks all fields to make sure this is a valid bulk DID vendor.  If there is
+an error, returns the error, otherwise returns false.  Called by the insert
+and replace methods.
+
+=cut
+
+# the check method should currently be supplied - FS::Record contains some
+# data checking routines
+
+sub check {
+  my $self = shift;
+
+  my $error = 
+    $self->ut_numbern('vendornum')
+    || $self->ut_text('vendorname')
+  ;
+  return $error if $error;
+
+  $self->SUPER::check;
+}
+
+=back
+
+=head1 BUGS
+
+=head1 SEE ALSO
+
+L<FS::Record>, schema.html from the base documentation.
+
+=cut
+
+1;
+
diff --git a/FS/FS/lata.pm b/FS/FS/lata.pm
new file mode 100644 (file)
index 0000000..7b42555
--- /dev/null
@@ -0,0 +1,121 @@
+package FS::lata;
+
+use strict;
+use base qw( FS::Record );
+use FS::Record qw( qsearch qsearchs );
+
+=head1 NAME
+
+FS::lata - Object methods for lata records
+
+=head1 SYNOPSIS
+
+  use FS::lata;
+
+  $record = new FS::lata \%hash;
+  $record = new FS::lata { 'column' => 'value' };
+
+  $error = $record->insert;
+
+  $error = $new_record->replace($old_record);
+
+  $error = $record->delete;
+
+  $error = $record->check;
+
+=head1 DESCRIPTION
+
+An FS::lata object represents a LATA number/name.  FS::lata inherits from
+FS::Record.  The following fields are currently supported:
+
+=over 4
+
+=item latanum
+
+primary key
+
+=item description
+
+description
+
+
+=back
+
+=head1 METHODS
+
+=over 4
+
+=item new HASHREF
+
+Creates a new LATA.  To add the LATA to the database, see L<"insert">.
+
+Note that this stores the hash reference, not a distinct copy of the hash it
+points to.  You can ask the object for a copy with the I<hash> method.
+
+=cut
+
+# the new method can be inherited from FS::Record, if a table method is defined
+
+sub table { 'lata'; }
+
+=item insert
+
+Adds this record to the database.  If there is an error, returns the error,
+otherwise returns false.
+
+=cut
+
+# the insert method can be inherited from FS::Record
+
+=item delete
+
+Delete this record from the database.
+
+=cut
+
+# the delete method can be inherited from FS::Record
+
+=item replace OLD_RECORD
+
+Replaces the OLD_RECORD with this one in the database.  If there is an error,
+returns the error, otherwise returns false.
+
+=cut
+
+# the replace method can be inherited from FS::Record
+
+=item check
+
+Checks all fields to make sure this is a valid LATA.  If there is
+an error, returns the error, otherwise returns false.  Called by the insert
+and replace methods.
+
+=cut
+
+# the check method should currently be supplied - FS::Record contains some
+# data checking routines
+
+sub check {
+  my $self = shift;
+
+  my $error = 
+    $self->ut_numbern('latanum')
+    || $self->ut_text('description')
+  ;
+  return $error if $error;
+
+  $self->SUPER::check;
+}
+
+=back
+
+=head1 BUGS
+
+=head1 SEE ALSO
+
+L<FS::Record>, schema.html from the base documentation.
+
+=cut
+
+1;
+
index 0d59113..8bb6a5c 100644 (file)
@@ -145,7 +145,10 @@ sub check {
     || $self->ut_numbern('nxx')
     || $self->ut_numbern('station')
     || $self->ut_foreign_keyn('svcnum', 'cust_svc', 'svcnum' )
+    || $self->ut_foreign_keyn('ordernum', 'did_order', 'ordernum' )
     || $self->ut_textn('availbatch')
+    || $self->ut_textn('name')
+    || $self->ut_textn('rate_center_abbrev')
   ;
   return $error if $error;
 
@@ -187,8 +190,21 @@ sub process_batch_import {
   };
 
   my $opt = { 'table'   => 'phone_avail',
-              'params'  => [ 'availbatch', 'exportnum', 'countrycode' ],
-              'formats' => { 'default' => [ 'state', $numsub, 'name' ], },
+              'params'  => [ 'availbatch', 'exportnum', 'countrycode', 'ordernum' ],
+              'formats' => { 'default' => [ 'state', $numsub, 'name' ],
+                            'bulk' => [ 'state', $numsub, 'name', 'rate_center_abbrev' ],
+                          },
+             'postinsert_callback' => sub {  
+                   my $record = shift;
+                   if($record->ordernum) {
+                       my $did_order = qsearchs('did_order', 
+                                               { 'ordernum' => $record->ordernum } );
+                       if($did_order && !$did_order->received) {
+                           $did_order->received(time);
+                           $did_order->replace;
+                       }
+                   }
+               }, 
             };
 
   FS::Record::process_batch_import( $job, $opt, @_ );
index 58728e4..16c717b 100644 (file)
@@ -543,3 +543,9 @@ t/svc_cert.t
 FS/cust_main/Status.pm
 FS/cust_note_class.pm
 t/cust_note_class.t
+FS/lata.pm
+t/lata.t
+FS/did_vendor.pm
+t/did_vendor.t
+FS/did_order.pm
+t/did_order.t
diff --git a/FS/bin/freeside-lata-import b/FS/bin/freeside-lata-import
new file mode 100755 (executable)
index 0000000..295b40e
--- /dev/null
@@ -0,0 +1,80 @@
+#!/usr/bin/perl -w
+
+use strict;
+use Getopt::Std;
+use FS::UID qw(adminsuidsetup);
+use FS::Conf;
+use FS::Record qw(qsearch qsearchs dbh);
+use LWP::Simple;
+use HTML::TableExtract;
+use Data::Dumper;
+
+&untaint_argv; #what it sounds like  (eww)
+use vars qw(%opt);
+
+my $user = shift or die &usage;
+my $dbh = adminsuidsetup $user;
+
+my $content = get("http://www.localcallingguide.com/lca_listlata.php");
+my $te = new HTML::TableExtract();
+$te->parse($content);
+my $table = $te->first_table_found;
+my $sql = 'insert into lata (latanum, description) values ';
+my @sql;
+foreach my $row ( $table->rows ) {
+    my @row = @$row;
+    next unless $row[0] =~ /\d+/;
+    $row[1] =~ s/'//g;
+    push @sql, "( ${row[0]}, '${row[1]}')";
+}
+$sql .= join(',',@sql);
+
+my $sth = $dbh->prepare('delete from lata');
+$sth->execute or die $sth->errstr;
+
+$sth = $dbh->prepare($sql);
+$sth->execute or die $sth->errstr;
+
+$dbh->commit;
+
+###
+# subroutines
+###
+
+sub untaint_argv {
+  foreach $_ ( $[ .. $#ARGV ) { #untaint @ARGV
+    #$ARGV[$_] =~ /^([\w\-\/]*)$/ || die "Illegal arguement \"$ARGV[$_]\"";
+    # Date::Parse
+    $ARGV[$_] =~ /^(.*)$/ || die "Illegal arguement \"$ARGV[$_]\"";
+    $ARGV[$_]=$1;
+  }
+}
+
+sub usage {
+  die "Usage:\n  freeside-lata-import user \n";
+}
+
+###
+# documentation
+###
+
+=head1 NAME
+
+freeside-lata-import - Pull LATA data from and insert into LATA table
+
+=head1 SYNOPSIS
+
+  freeside-lata-import user
+
+=head1 DESCRIPTION
+
+user - name of an internal Freeside user
+
+=head1 BUGS
+
+=head1 SEE ALSO
+
+L<FS::lata>
+
+=cut
+
diff --git a/FS/t/did_order.t b/FS/t/did_order.t
new file mode 100644 (file)
index 0000000..ae58719
--- /dev/null
@@ -0,0 +1,5 @@
+BEGIN { $| = 1; print "1..1\n" }
+END {print "not ok 1\n" unless $loaded;}
+use FS::did_order;
+$loaded=1;
+print "ok 1\n";
diff --git a/FS/t/did_vendor.t b/FS/t/did_vendor.t
new file mode 100644 (file)
index 0000000..b8df3ee
--- /dev/null
@@ -0,0 +1,5 @@
+BEGIN { $| = 1; print "1..1\n" }
+END {print "not ok 1\n" unless $loaded;}
+use FS::did_vendor;
+$loaded=1;
+print "ok 1\n";
diff --git a/FS/t/lata.t b/FS/t/lata.t
new file mode 100644 (file)
index 0000000..a70c3cb
--- /dev/null
@@ -0,0 +1,5 @@
+BEGIN { $| = 1; print "1..1\n" }
+END {print "not ok 1\n" unless $loaded;}
+use FS::lata;
+$loaded=1;
+print "ok 1\n";
diff --git a/httemplate/browse/did_order.html b/httemplate/browse/did_order.html
new file mode 100644 (file)
index 0000000..54c2bd3
--- /dev/null
@@ -0,0 +1,65 @@
+<% include( 'elements/browse.html',
+                 'title'       => 'Bulk DID Orders',
+                 'html_init'   => $html_init,
+                 'name'        => 'bulk DID orders',
+                 'disableable' => 0,
+                 'query'       => { 'table'     => 'did_order',
+                                   'addl_from' => 'left join did_vendor using (vendornum) 
+                                                   left join lata using (latanum)',
+                                    'hashref'   => {},
+                                    'order_by' => 'ORDER BY ordernum',
+                                  },
+                 'count_query' => $count_query,
+                 'header'      => $header,
+                 'fields'      => $fields,
+                 'links'       => $links,
+             )
+%>
+<%init>
+
+die "access denied"
+  unless $FS::CurrentUser::CurrentUser->access_right('Import');
+
+my $conf = new FS::Conf;
+my $date_format = $conf->config('date_format') || '%m/%d/%Y';
+
+my $html_init = 
+  qq!<A HREF="${p}edit/did_order.html"><I>Add a bulk DID order</I></A><BR><BR>!;
+
+my $count_query = 'SELECT COUNT(*) FROM did_order';
+
+my $link = [ $p.'edit/did_order.html?', 'ordernum' ];
+
+my $display_date = sub {
+    my $date = shift;
+    return '' unless $date;
+    time2str($date_format, $date);
+};
+
+my $header = [ '#', 'Vendor',' Vendor Order #', 'MSA', 'LATA #', 'LATA', 
+               'Rate Center', 'State', 'Quantity', 'Submitted', 'Confirmed',
+               'Received', 
+           ];
+my $links  = [ ];
+my $fields = [  sub {
+                   my $did_order = shift;
+                   if($did_order->received) {
+                       push @$links, $link;
+                   }
+                   else {
+                       return $did_order->ordernum;
+                   }
+               }, 'vendorname', 'vendor_order_id', 'msa', 'latanum',
+               'description', 'rate_center', 'state', 'quantity', 
+               sub { &$display_date(shift->submitted); }, 
+               sub { &$display_date(shift->confirmed); }, 
+               sub { 
+                   my $did_order = shift;
+                   my $ordernum = $did_order->ordernum;
+                   return &$display_date($did_order->received) 
+                       if $did_order->received;
+                   "<A HREF='${p}misc/phone_avail-import.html?ordernum=$ordernum'>Upload Received</A>";
+               }, 
+            ];
+
+</%init>
diff --git a/httemplate/browse/did_vendor.html b/httemplate/browse/did_vendor.html
new file mode 100644 (file)
index 0000000..04904ec
--- /dev/null
@@ -0,0 +1,32 @@
+<% include( 'elements/browse.html',
+                 'title'       => 'Bulk DID Vendors',
+                 'html_init'   => $html_init,
+                 'name'        => 'bulk DID vendors',
+                 'disableable' => 0,
+                 'query'       => { 'table'     => 'did_vendor',
+                                    'hashref'   => {},
+                                    'order_by' => 'ORDER BY vendornum',
+                                  },
+                 'count_query' => $count_query,
+                 'header'      => $header,
+                 'fields'      => $fields,
+                 'links'       => $links,
+             )
+%>
+<%init>
+
+die "access denied"
+  unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my $html_init = 
+  qq!<A HREF="${p}edit/did_vendor.html"><I>Add a bulk DID vendor</I></A><BR><BR>!;
+
+my $count_query = 'SELECT COUNT(*) FROM did_vendor';
+
+my $link = [ $p.'edit/did_vendor.html?', 'vendornum' ];
+
+my $header = [ '#', 'Vendor' ];
+my $fields = [ 'vendornum', 'vendorname' ];
+my $links  = [ $link, $link ];
+
+</%init>
diff --git a/httemplate/edit/did_order.html b/httemplate/edit/did_order.html
new file mode 100644 (file)
index 0000000..ac8f336
--- /dev/null
@@ -0,0 +1,46 @@
+<% include( 'elements/edit.html',
+              'fields' => [
+                           { field => 'vendornum',
+                             type => 'select-table',
+                             name_col => 'vendorname',
+                             table => 'did_vendor',
+                             disable_empty => 1,
+                           },
+                           'vendor_order_id',
+                           'msa',
+                           { field => 'latanum',
+                             type => 'select-table',
+                             name_col => 'description',
+                             table => 'lata',
+                             disable_empty => 1,
+                             label_showkey => 1,
+                           },
+                           'rate_center',
+                           { field => 'state',
+                             type => 'select-state',
+                             country => 'US',
+                           },
+                           'quantity',
+                           { field => 'confirmed',
+                             type => 'input-date-field',
+                           },
+                          ],
+              'labels' => { 
+                           'vendornum' => 'Vendor',
+                           'vendor_order_id' => 'Vendor Order #',
+                           'msa'       => 'MSA',
+                           'latanum' => 'LATA',
+                           'rate_center' => 'Rate Center',
+                          },
+              'viewall_dir' => 'browse',
+             'table' => 'did_order',
+             'name' => 'Bulk DID Order',
+           )
+          
+%>
+<%init>
+
+die "access denied"
+  unless $FS::CurrentUser::CurrentUser->access_right('Import');
+
+</%init>
diff --git a/httemplate/edit/did_vendor.html b/httemplate/edit/did_vendor.html
new file mode 100644 (file)
index 0000000..b6d57b5
--- /dev/null
@@ -0,0 +1,19 @@
+<% include( 'elements/edit.html',
+              'fields' => [
+                            'vendorname',
+                          ],
+              'labels' => { 
+                            'vendorname'   => 'Vendor name',
+                          },
+              'viewall_dir' => 'browse',
+             'table' => 'did_vendor',
+             'name' => 'Bulk DID Vendor',
+           )
+          
+%>
+<%init>
+
+die "access denied"
+  unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+</%init>
index 89f0fcc..6d88e5d 100644 (file)
@@ -311,6 +311,11 @@ Example:
 %     foreach grep exists($f->{$_}),
 %       qw( hashref agent_virt agent_null agent_null_right );
 %
+%   # select-country
+%   $include_common{$_} = $f->{$_}
+%     foreach grep exists($f->{$_}),
+%       qw( country );
+%
 %   #htmlarea
 %   $include_common{$_} = $f->{$_}
 %     foreach grep exists($f->{$_}), qw( width height );
diff --git a/httemplate/edit/process/did_order.html b/httemplate/edit/process/did_order.html
new file mode 100644 (file)
index 0000000..0c9a3f0
--- /dev/null
@@ -0,0 +1,21 @@
+<% include( 'elements/process.html',
+               'table'       => 'did_order',
+               'viewall_dir' => 'browse',
+              'value_callback' => $value_callback,
+           )
+%>
+<%init>
+
+unless($cgi->param('submitted')) {
+    $cgi->param('submitted',time);
+}
+
+my $value_callback = sub {
+     my ($field, $value) = @_;
+     ($field =~ /ed$/ && $value !~ /^\d+$/) ? parse_datetime($value) : $value;
+};
+
+die "access denied"
+  unless $FS::CurrentUser::CurrentUser->access_right('Import');
+
+</%init>
diff --git a/httemplate/edit/process/did_vendor.html b/httemplate/edit/process/did_vendor.html
new file mode 100644 (file)
index 0000000..891a453
--- /dev/null
@@ -0,0 +1,11 @@
+<% include( 'elements/process.html',
+               'table'       => 'did_vendor',
+               'viewall_dir' => 'browse',
+           )
+%>
+<%init>
+
+die "access denied"
+  unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+</%init>
index a981abd..ae58cda 100644 (file)
@@ -380,6 +380,8 @@ $tools_menu{'Process payment batches'} = [ $fsurl.'search/pay_batch.cgi?magic=_d
      && $curuser->access_right('Process batches');
 $tools_menu{'Download invoice batches'} = [ $fsurl.'search/bill_batch.cgi' ] 
   if $conf->exists('invoice_print_pdf');
+$tools_menu{'Bulk DID Orders'} =  [ $fsurl.'browse/did_order.html', 'View/manage bulk DID orders' ]
+  if $curuser->access_right('Import');
 $tools_menu{'Job Queue'} =  [ $fsurl.'search/queue.html', 'View pending job queue' ]
   if $curuser->access_right('Job queue');
 $tools_menu{'Ticketing'} = [ \%tools_ticketing, 'Ticketing tools' ]
@@ -496,6 +498,7 @@ tie my %config_broadband, 'Tie::IxHash',
 
 tie my %config_phone, 'Tie::IxHash',
   'View/Edit phone device types' => [ $fsurl.'browse/part_device.html', 'Phone device types' ],
+  'View/Edit bulk DID vendors' => [ $fsurl.'browse/did_vendor.html', 'Bulk DID vendors' ],
 ;
 
 tie my %config_misc, 'Tie::IxHash';
diff --git a/httemplate/elements/tr-select-state.html b/httemplate/elements/tr-select-state.html
new file mode 100644 (file)
index 0000000..1a62ae5
--- /dev/null
@@ -0,0 +1,19 @@
+% unless ( $opt{'js_only'} ) {
+    <% include('tr-td-label.html', @_ ) %>
+
+      <TD <% $style %>>
+% }
+        
+       <% include( '/elements/select-state.html', %opt ) %>
+
+% unless ( $opt{'js_only'} ) {
+      </TD>
+    </TR>
+% }
+<%init>
+
+my %opt = @_;
+
+my $style = $opt{'cell_style'} ? 'STYLE="'. $opt{'cell_style'}. '"' : '';
+
+</%init>
index c664c07..fcbfcc3 100644 (file)
@@ -7,7 +7,7 @@ Import a file containing phone numbers (DIDs).
               'name'      => 'PhonenumImportForm',
               'action'    => 'process/phone_avail-import.html',
               'num_files' => 1,
-              'fields'    => [ 'format', 'availbatch', 'exportnum', 'countrycode' ],
+              'fields'    => [ 'format', 'availbatch', 'exportnum', 'countrycode', 'ordernum' ],
               'message'   => 'DID import successful',
               'url'       => $p."search/phone_avail.html?availbatch=$availbatch",
           )
@@ -15,10 +15,22 @@ Import a file containing phone numbers (DIDs).
 
 <% &ntable("#cccccc", 2) %>
 
-  <INPUT TYPE="hidden" NAME="format" VALUE="default">
 
   <INPUT TYPE="hidden" NAME="availbatch" VALUE="<% $availbatch %>">
 
+% if ( $ordernum ) {
+    <TR>
+       <TD ALIGN="RIGHT">Bulk DID Order #</TD>
+       <TD><% $ordernum %>
+           <INPUT TYPE="hidden" NAME="ordernum" VALUE="<% $ordernum %>">
+       </TD>
+    </TR>
+% } 
+  <TR>
+    <TD ALIGN="RIGHT">Import Format</TD>
+    <TD><% $format %><INPUT TYPE="hidden" NAME="format" VALUE="<% $format %>"></TD>
+  </TR>
+
   <% include( '/elements/tr-select-table.html',
                 'table'       => 'part_export',
                 'name_col'    => 'label',
@@ -65,15 +77,18 @@ Import a file containing phone numbers (DIDs).
 Uploaded files can be CSV (comma-separated value) files or Excel spreadsheets.  The file should have a .CSV or .XLS extension.
 <BR><BR>
 
-<b>Default</b> format has the following field order: <i>state, number, name</i>
+<b>Default</b> format has the following field order: <i>state, number, name</i><br>
+<b>Bulk</b> format has the following field order: <i>state, number, rate center, rate_center_abbrev</i>
 <BR><BR>
-
 Field information:
 <ul>
   <li><i>state</i>: Two-letter state code, i.e. "CA"
   <li><i>number</i>: Phone number
   <li><i>name</i>: optional, rate center
+  <li><i>rate center</i>: rate center (required)
+  <li><i>rate_center_abbrev</i>: rate center abbreviation
 </ul>
+<BR><BR>
 
 <% include('/elements/footer.html') %>
 
@@ -84,6 +99,15 @@ die "access denied"
 
 my $conf = new FS::Conf;
 
+my $ordernum = $cgi->param('ordernum');
+$ordernum = '' unless $ordernum =~ /^\d+$/;
+
+die 'invalid ordernum' 
+    unless (!$ordernum || qsearchs('did_order', { 'ordernum' => $ordernum }));
+
+my $format = 'default';
+$format = 'bulk' if $ordernum;
+
 my $availbatch =
   time2str('webimport-%Y/%m/%d-%T'. "-$$-". rand() * 2**32, time);