added basic LNP capability to svc_phone including SS, RT10948
authorlevinse <levinse>
Sun, 26 Dec 2010 04:09:26 +0000 (04:09 +0000)
committerlevinse <levinse>
Sun, 26 Dec 2010 04:09:26 +0000 (04:09 +0000)
16 files changed:
FS/FS/ClientAPI/MyAccount.pm
FS/FS/Conf.pm
FS/FS/Record.pm
FS/FS/Schema.pm
FS/FS/svc_phone.pm
fs_selfservice/FS-SelfService/cgi/provision_svc_phone.html
fs_selfservice/FS-SelfService/cgi/selfservice.cgi
fs_selfservice/FS-SelfService/cgi/ws_list.html
httemplate/edit/elements/edit.html
httemplate/edit/part_svc.cgi
httemplate/edit/process/svc_phone.html
httemplate/edit/svc_phone.cgi
httemplate/elements/select-lnp_status.html [new file with mode: 0644]
httemplate/elements/tr-input-date-field.html
httemplate/elements/tr-select-lnp_status.html [new file with mode: 0644]
httemplate/view/svc_phone.cgi

index 9a20285..d619e84 100644 (file)
@@ -18,6 +18,7 @@ use FS::Conf;
 use FS::Record qw(qsearch qsearchs dbh);
 use FS::Msgcat qw(gettext);
 use FS::Misc qw(card_types);
+use FS::Misc::DateTime qw(parse_datetime);
 use FS::ClientAPI_SessionCache;
 use FS::svc_acct;
 use FS::svc_domain;
@@ -978,6 +979,7 @@ sub list_pkgs {
     'wholesale_view' => 1,
     'login_svcpart' => [ $conf->config('selfservice_server-login_svcpart') ],
     'date_format' => $conf->config('date_format') || '%m/%d/%Y',
+    'lnp' => $conf->exists('svc_phone-lnp'),
       };
   }
 
@@ -1568,7 +1570,23 @@ sub cancel_pkg {
 
 sub provision_phone {
  my $p = shift;
- my @bulkdid = @{$p->{'bulkdid'}};
+ my @bulkdid;
+ @bulkdid = @{$p->{'bulkdid'}} if $p->{'bulkdid'};
+
+# single DID LNP
+ unless($p->{'lnp'}) {
+    $p->{'lnp_desired_due_date'} = parse_datetime($p->{'lnp_desired_due_date'});
+    $p->{'lnp_status'} = "portingin";
+    return _provision( 'FS::svc_phone',
+                 [qw(lnp_desired_due_date lnp_other_provider 
+                   lnp_other_provider_account phonenum countrycode lnp_status)],
+                 [qw(phonenum countrycode)],
+                 $p,
+                 @_
+               );
+ }
+
+# single DID order
  unless (scalar(@bulkdid)) {
     return _provision( 'FS::svc_phone',
                  [qw(phonenum countrycode)],
@@ -1578,7 +1596,7 @@ sub provision_phone {
                );
  }
 
-# bulk case
+# bulk DID order case
   my $error;
   foreach my $did ( @bulkdid ) {
     $did =~ s/[^0-9]//g;
index 132ee47..fbf18cb 100644 (file)
@@ -3789,6 +3789,13 @@ and customer address. Include units.',
     'description' => 'Maximum length of the phone service "Name" field (svc_phone.phone_name).  Sometimes useful to limit this (to 15?) when exporting as Caller ID data.',
     'type'        => 'text',
   },
+  
+  {
+    'key'         => 'svc_phone-lnp',
+    'section'     => '',
+    'description' => 'Enables Number Portability features for svc_phone',
+    'type'        => 'checkbox',
+  },
 
   {
     'key'         => 'default_phone_countrycode',
index 16520f4..2e2612e 100644 (file)
@@ -2589,6 +2589,20 @@ sub ut_enum {
   return "Illegal (enum) field $field: ". $self->getfield($field);
 }
 
+=item ut_enumn COLUMN CHOICES_ARRAYREF
+
+Like ut_enum, except the null value is also allowed.
+
+=cut
+
+sub ut_enumn {
+  my( $self, $field, $choices ) = @_;
+  $self->getfield($field)
+    ? $self->ut_enum($field, $choices)
+    : '';
+}
+
+
 =item ut_foreign_key COLUMN FOREIGN_TABLE FOREIGN_COLUMN
 
 Check/untaint a foreign column key.  Call a regular ut_ method (like ut_number)
index 253eb66..7224341 100644 (file)
@@ -2873,6 +2873,13 @@ sub tables_hashref {
         'pbxsvc',           'int', 'NULL',      '', '', '',
         'domsvc',           'int', 'NULL',      '', '', '', 
         'locationnum',      'int', 'NULL', '', '', '',
+        'lnp_status',   'varchar', 'NULL', $char_d, '', '',
+        'portable',    'char', 'NULL',       1,  '', '', 
+        'lrn',     'char',     'NULL',      10, '', '', 
+       'lnp_desired_due_date',     'int', 'NULL',       '', '', '',
+       'lnp_due_date',     'int', 'NULL',       '', '', '',
+        'lnp_other_provider', 'varchar', 'NULL', $char_d,  '', '',
+        'lnp_other_provider_account', 'varchar', 'NULL', $char_d,  '', '',
       ],
       'primary_key' => 'svcnum',
       'unique' => [],
index adf7a6c..be6e2f7 100644 (file)
@@ -97,6 +97,7 @@ points to.  You can ask the object for a copy with the I<hash> method.
 # the new method can be inherited from FS::Record, if a table method is defined
 #
 sub table_info {
+ my %dis2 = ( disable_inventory=>1, disable_select=>1 );
   {
     'name' => 'Phone number',
     'sorts' => 'phonenum',
@@ -134,6 +135,26 @@ sub table_info {
                            disable_inventory => 1,
                            disable_select    => 1,
                          },
+       'lnp_status' => {       label => 'LNP Status',
+                               type => 'select-lnp_status.html',
+                               %dis2,
+                       },
+       'portable' =>   {       label => 'Portable?', %dis2, },
+       'lrn'   =>      {       label => 'LRN', 
+                               disable_inventory => 1, 
+                       },
+       'lnp_desired_due_date' =>
+                       { label => 'LNP Desired Due Date', %dis2 },
+       'lnp_due_date' =>
+                       { label => 'LNP Due Date', %dis2 },
+       'lnp_other_provider' =>
+                       {       label => 'LNP Other Provider', 
+                               disable_inventory => 1, 
+                       },
+       'lnp_other_provider_account' =>
+                       {       label => 'LNP Other Provider Account #', 
+                               %dis2 
+                       },
     },
   };
 }
@@ -392,6 +413,13 @@ sub check {
     || $self->ut_foreign_keyn('pbxsvc', 'svc_pbx',    'svcnum' )
     || $self->ut_foreign_keyn('domsvc', 'svc_domain', 'svcnum' )
     || $self->ut_foreign_keyn('locationnum', 'cust_location', 'locationnum')
+    || $self->ut_numbern('lrn')
+    || $self->ut_numbern('lnp_desired_due_date')
+    || $self->ut_numbern('lnp_due_date')
+    || $self->ut_textn('lnp_other_provider')
+    || $self->ut_textn('lnp_other_provider_account')
+    || $self->ut_enumn('lnp_status', ['','portingin','portingout','portedin','native'])
+    || $self->ut_enumn('portable', ['','Y'])
   ;
   return $error if $error;
 
index 3ca7a12..ab9827e 100644 (file)
@@ -1,6 +1,15 @@
-<%= $url = "$selfurl?session=$session_id;action="; ''; %>
-<%= include('header', 'Setup phone number') %>
+<%= $url = "$selfurl?session=$session_id;action="; 
+ $heading2 = $lnp ? "Port-In Number" : "Setup phone number";
+ '';
+%>
+<%= include('header', $heading2) %>
 <%=
+
+sub lnp_textfield {
+    my ($name,$label) = (shift,shift);
+   qq!<tr><td>$label</td><td><input type="text" name="$name"></td></tr>!;
+}
+
 if($error) {
     $OUT .= qq!<div style="color:red; font-size: 115%">$error</div>!;
 }
@@ -12,10 +21,21 @@ if($error) {
 <INPUT TYPE="hidden" NAME="pkgnum" VALUE="<%= $pkgnum %>">
 <INPUT TYPE="hidden" NAME="svcpart" VALUE="<%= $svcpart %>">
 <INPUT TYPE="hidden" NAME="numavail" VALUE="<%= $numavail %>">
-<%= didselector('field' => 'phonenum', 
+<%=
+if($lnp) {
+    $OUT .= "<table>"
+           . qq!<input type="hidden" name="lnp" value="1">!
+           . lnp_textfield(phonenum,"Phone Number")
+           . lnp_textfield("lnp_desired_due_date","Requested Port-In Date")
+           . lnp_textfield("lnp_other_provider","Current Provider")
+           . lnp_textfield("lnp_other_provider_account","Current Provider's Account #")
+           . "</table>";
+} else {
+    didselector('field' => 'phonenum', 
                'svcpart' => $svcpart,
                'bulknum' => $numavail,
                );
+}
 %>
 <BR><BR><INPUT TYPE="submit" VALUE="Setup">
 </FORM>
index 0d3bed8..5b2d298 100644 (file)
@@ -710,6 +710,7 @@ sub provision_svc {
   $action .= "_$1";
 
   $result->{'numavail'} = $cgi->param('numavail');
+  $result->{'lnp'} = $cgi->param('lnp');
 
   $result;
 }
@@ -717,13 +718,25 @@ sub provision_svc {
 sub process_svc_phone {
     my @bulkdid = $cgi->param('bulkdid');
     my $phonenum = $cgi->param('phonenum');
-
-    my $result = provision_phone (
-       'session_id' => $session_id,
-       'bulkdid' => [ @bulkdid ],
-       'countrycode' => '1',
-        map { $_ => $cgi->param($_) } qw( pkgnum svcpart phonenum )
-    );
+    my $lnp = $cgi->param('lnp');
+
+    my $result;
+    if($lnp) {
+       $result = provision_phone (
+           'session_id' => $session_id,
+           'countrycode' => '1',
+            map { $_ => $cgi->param($_) } qw( pkgnum svcpart phonenum 
+               lnp_desired_due_date lnp_other_provider 
+               lnp_other_provider_account )
+       );
+    } else {
+       $result = provision_phone (
+           'session_id' => $session_id,
+           'bulkdid' => [ @bulkdid ],
+           'countrycode' => '1',
+            map { $_ => $cgi->param($_) } qw( pkgnum svcpart phonenum )
+       );
+    }
 
     if ( exists $result->{'error'} && $result->{'error'} ) { 
        $action = 'provision_svc_phone';
index 6b23b7d..2bdcd74 100644 (file)
@@ -57,6 +57,12 @@ if ( $pkgpart ) {
                    . qq!$part_svc->{'svc'}</A> ($part_svc->{'num_avail'}!
                    . qq! available)<BR><BR>!;
                $OUT .= $link if $part_svc->{'can_get_dids'};
+
+               if($part_svc->{'svcdb'} eq 'svc_phone' && $lnp) {
+                   $OUT .= qq!<A HREF="${url}provision_svc;lnp=1;!
+                   . qq!pkgnum=$pkg->{'pkgnum'};svcpart=$part_svc->{'svcpart'}!
+                   . qq!">Port-In $part_svc->{'svc'}</A>!;
+               }
            }
 
            $OUT .= "</TD></TR>";
index 142d0c3..cab5167 100644 (file)
@@ -356,6 +356,19 @@ Example:
 %         %include_common,
 %         %opt,
 %     );
+%
+%     if ( $include eq 'tr-input-date-field' ) {
+%      # it's either hacking it here, or changing a lot more stuff
+%      @include = (
+%              "/elements/$include.html", {
+%                      'name' => $field,
+%                      'value' => $opt{curr_value},
+%                      'label' => $label,
+%                      'noinit' => $f->{noinit},
+%              }
+%      );
+%     }
+%
 %     @include;
 %   };
 %
index d156ccd..437f7e8 100755 (executable)
@@ -334,6 +334,15 @@ that field.
 %                             'multiple'     => ($flag eq 'S'),
 %                          );
 %
+%        } elsif ( $def->{type} eq 'select-lnp_status.html' ) {
+%
+%          $html .= include('/elements/select-lnp_status.html',
+%                             'curr_value'   => $value,
+%                             'element_name' => "${layer}__${field}",
+%                             'element_etc'  => $disabled,
+%                             'multiple'     => ($flag eq 'S'),
+%                          );
+%
 %        } elsif ( $def->{type} eq 'radius_usergroup_selector' ) {
 %
 %          #XXX disable the RADIUS usergroup selector?  ugh it sure does need
index e02ec5c..ddc9382 100644 (file)
@@ -1,6 +1,7 @@
 <% include( 'elements/svc_Common.html',
                'table'    => 'svc_phone',
                'args_callback' => $args_callback,
+              'value_callback' => $value_callback,
            )
 %>
 <%init>
@@ -24,6 +25,9 @@ my $args_callback = sub {
 
 };
 
-
+my $value_callback = sub {
+     my ($field, $value) = @_;
+     ($field =~ /_date$/) ? parse_datetime($value) : $value;
+};
 
 </%init>
index b77d962..6482165 100644 (file)
@@ -1,17 +1,6 @@
 <% include( 'elements/svc_Common.html',
                'table'    => 'svc_phone',
                'fields'   => \@fields,
-               'labels'   => {
-                               'svcnum'       => 'Service',
-                               'countrycode'  => 'Country code',
-                               'phonenum'     => 'Phone number',
-                               'domsvc'       => 'Domain',
-                               'sip_password' => 'SIP password',
-                               'pin'          => 'Voicemail PIN',
-                               'phone_name'   => 'Name',
-                               'pbxsvc'       => 'PBX',
-                               'locationnum'  => 'E911 location',
-                             },
                'svc_new_callback' => sub {
                  my( $cgi, $svc_x, $part_svc, $cust_pkg, $fields, $opt ) = @_;
                  $svc_x->locationnum($cust_pkg->locationnum) if $cust_pkg;
@@ -73,5 +62,29 @@ push @fields, { field => 'pbxsvc',
               { field => 'custnum', type=> 'hidden' }, #for new cust_locations
 ;
 
+if ( $conf->exists('svc_phone-lnp') ) {
+    push @fields,
+            { value   => 'Number Portability',
+             type    => 'tablebreak-tr-title',
+                               colspan => 7,
+            },
+           {   field => 'lnp_status',
+               type => 'select-lnp_status',
+           },
+           {   field => 'portable',
+               type => 'checkbox',
+           },
+            'lrn',
+           {   field => 'lnp_desired_due_date',
+               type => 'input-date-field',
+           },
+           {   field => 'lnp_due_date',
+               type => 'input-date-field',
+               noinit => 1,
+           },
+            'lnp_other_provider',
+            'lnp_other_provider_account',
+;
+}
 
 </%init>
diff --git a/httemplate/elements/select-lnp_status.html b/httemplate/elements/select-lnp_status.html
new file mode 100644 (file)
index 0000000..f4910e0
--- /dev/null
@@ -0,0 +1,22 @@
+<SELECT NAME = "<% $opt{'element_name'} || $opt{'field'} || 'lnp_status' %>"
+        <% $opt{'element_etc'} %>
+>
+% unless ( $opt{'disable_empty'} ) {
+    <OPTION VALUE=""><% $opt{'empty_label'} || '' %></OPTION>
+% }
+% foreach my $selopt ( keys %seloptions ) {
+%  my $selected = ($selopt eq $opt{'curr_value'}) ? 'SELECTED' : '';
+    <OPTION VALUE="<%$selopt%>" <% $selected %>><% $seloptions{$selopt} %></OPTION>
+% }
+</SELECT>
+<%init>
+
+my %opt = @_;
+
+my %seloptions = ( 
+               'native' => 'Native',
+               'portedin' => 'Ported In',
+               'portingin' => 'Porting In',
+               'portingout' => 'Porting Out',
+           );
+</%init>
index ff4996f..5400fcb 100644 (file)
@@ -1,8 +1,9 @@
-
+% unless ( $noinit ) {
 <LINK REL="stylesheet" TYPE="text/css" HREF="<%$fsurl%>elements/calendar-win2k-2.css" TITLE="win2k-2">
 <SCRIPT TYPE="text/javascript" SRC="<%$fsurl%>elements/calendar_stripped.js"></SCRIPT>
 <SCRIPT TYPE="text/javascript" SRC="<%$fsurl%>elements/calendar-en.js"></SCRIPT>
 <SCRIPT TYPE="text/javascript" SRC="<%$fsurl%>elements/calendar-setup.js"></SCRIPT>
+% }
 
 <TR>
   <TD ALIGN="right"><% $label %></TD>
@@ -23,7 +24,7 @@
 
 <%init>
 
-my($name, $value, $label, $format, $usedatetime);
+my($name, $value, $label, $format, $usedatetime, $noinit);
 if ( ref($_[0]) ) {
   my $opt = shift;
   $name        = $opt->{'name'};
@@ -31,6 +32,7 @@ if ( ref($_[0]) ) {
   $label       = $opt->{'label'};
   $format      = $opt->{'format'};
   $usedatetime = $opt->{'usedatetime'};
+  $noinit      = $opt->{'noinit'};
 } else {
   ($name, $value, $label, $format, $usedatetime) = @_;
 }
diff --git a/httemplate/elements/tr-select-lnp_status.html b/httemplate/elements/tr-select-lnp_status.html
new file mode 100644 (file)
index 0000000..a71e94b
--- /dev/null
@@ -0,0 +1,14 @@
+  <TR>
+    <TD ALIGN="right"><% $opt{'label'} || 'LNP Status' %></TD>
+    <TD>
+      <% include('/elements/select-lnp_status.html',
+                   'curr_value' => $opt{'curr_value'},
+                )
+      %>
+    </TD>
+  </TR>
+<%init>
+
+my %opt = @_;
+
+</%init>
index 27d270c..94948a7 100644 (file)
@@ -1,15 +1,7 @@
 <% include('elements/svc_Common.html',
               'table'     => 'svc_phone',
               'fields'    => \@fields,
-              'labels'    => {
-                               'countrycode'  => 'Country code',
-                               'phonenum'     => 'Phone number',
-                               'domain'       => 'Domain',
-                               'pbx_title'    => 'PBX',
-                               'sip_password' => 'SIP password',
-                               'pin'          => 'PIN',
-                               'phone_name'   => 'Name',
-                             },
+             'labels'    => \%labels,
               'html_foot' => $html_foot,
           )
 %>
 my $conf = new FS::Conf;
 my $countrydefault = $conf->config('countrydefault') || 'US';
 
+my $fields = FS::svc_phone->table_info->{'fields'};
+my %labels = map { $_ =>  ( ref($fields->{$_})
+                             ? $fields->{$_}{'label'}
+                             : $fields->{$_}
+                         );
+                 } keys %$fields;
+
 my @fields = qw( countrycode phonenum );
 push @fields, 'domain' if $conf->exists('svc_phone-domain');
 push @fields, qw( pbx_title sip_password pin phone_name );
 
+if ( $conf->exists('svc_phone-lnp') ) {
+push @fields, 'lnp_status',
+           { field => 'portable', type => 'checkbox', },
+           'lrn',
+           { field => 'lnp_desired_due_date', type => 'date', },
+           { field => 'lnp_due_date', type => 'date', },
+           'lnp_other_provider',
+           'lnp_other_provider_account';
+}
+
 my $html_foot = sub {
   my $svc_phone = shift;