[freeside-commits] branch master updated. 7c3806cdbb65e125227fc78a3acbf188097a7e33

Ivan ivan at 420.am
Fri Dec 14 19:32:46 PST 2012


The branch, master has been updated
       via  7c3806cdbb65e125227fc78a3acbf188097a7e33 (commit)
      from  3bed798b18bf3a01343cd53fd3cfdf3463041bea (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 7c3806cdbb65e125227fc78a3acbf188097a7e33
Author: Ivan Kohler <ivan at freeside.biz>
Date:   Fri Dec 14 19:32:44 2012 -0800

    DID selection for fibernetics, RT#19883

diff --git a/FS/FS/part_export.pm b/FS/FS/part_export.pm
index ed66b41..5d65062 100644
--- a/FS/FS/part_export.pm
+++ b/FS/FS/part_export.pm
@@ -628,6 +628,10 @@ sub info {
   };
 }
 
+#default fallbacks... FS::part_export::DID_Common ?
+sub get_dids_can_tollfree { 0; }
+sub get_dids_npa_select   { 1; }
+
 =back
 
 =head1 SUBROUTINES
diff --git a/FS/FS/part_export/fibernetics_did.pm b/FS/FS/part_export/fibernetics_did.pm
new file mode 100644
index 0000000..76391e8
--- /dev/null
+++ b/FS/FS/part_export/fibernetics_did.pm
@@ -0,0 +1,176 @@
+package FS::part_export::fibernetics_did;
+use base qw( FS::part_export );
+
+use strict;
+use vars qw( %info $DEBUG );
+use Data::Dumper;
+use URI::Escape;
+#use Locale::SubCountry;
+#use FS::Record qw(qsearch dbh);
+use XML::Simple;
+#use Net::HTTPS::Any qw( 0.10 https_get );
+use LWP::UserAgent;
+use HTTP::Request::Common;
+
+$DEBUG = 0;
+
+tie my %options, 'Tie::IxHash',
+  'country' => { 'label' => 'Country', 'default' => 'CA', size=>2, },
+;
+
+%info = (
+  'svc'        => 'svc_phone',
+  'desc'       => 'Provision phone numbers to Fibernetics web services API',
+  'options'    => \%options,
+  'notes'      => '',
+);
+
+sub rebless { shift; }
+
+sub get_dids_can_tollfree { 0; };
+sub get_dids_npa_select   { 0; };
+
+# i guess we could get em from the API, but since its returning states without
+#  availability, there's no advantage
+    # not really needed, we maintain our own list of provinces, but would
+    #  help to hide the ones without availability (need to fix the selector too)
+our @states = (
+  'Alberta',
+  'British Columbia',
+  'Ontario',
+  'Quebec',
+  #'Saskatchewan',
+  #'The Territories',
+  #'PEI/Nova Scotia',
+  #'Manitoba',
+  #'Newfoundland',
+  #'New Brunswick',
+);
+
+sub get_dids {
+  my $self = shift;
+  my %opt = ref($_[0]) ? %{$_[0]} : @_;
+
+  if ( $opt{'tollfree'} ) {
+    warn 'Fibernetics DID provisioning does not yet support toll-free numbers';
+    return [];
+  }
+
+  my %query_hash = ();
+
+  #ratecenter + state: return numbers (more structured names, npa selection)
+  #areacode + exchange: return numbers
+  #areacode: return city/ratecenter/whatever
+  #state: return areacodes
+
+  #region + state: return numbers (arbitrary names, no npa selection)
+  #state: return regions
+
+#  if ( $opt{'areacode'} && $opt{'exchange'} ) { #return numbers
+#
+#    $query_hash{'region'} = $opt{'exchange'};
+#
+#  } elsif ( $opt{'areacode'} ) {
+#
+#    $query_hash{'npa'} = $opt{'areacode'};
+
+  #if ( $opt{'state'} && $opt{'region'} ) { #return numbers
+  if ( $opt{'region'} ) { #return numbers
+
+    #$query_hash{'province'} = $country->full_name($opt{'state'});
+    $query_hash{'region'}   = $opt{'region'}
+
+  } elsif ( $opt{'state'} ) { #return regions
+
+    #my $country = new Locale::SubCountry( $self->option('country') );
+    #$query_hash{'province'}   = $country->full_name($opt{'state'});
+    $query_hash{'province'}   = $opt{'state'};
+    $query_hash{'listregion'} = 1;
+
+  } else { #nothing passed, return states (provinces)
+
+    return \@states;
+
+  }
+
+
+  my $url = 'http://'. $self->machine. '/porta/cgi-bin/porta_query.cgi';
+  if ( keys %query_hash ) {
+    $url .= '?'. join('&', map "$_=". uri_escape($query_hash{$_}),
+                             keys %query_hash
+                     );
+  }
+  warn $url if $DEBUG;
+
+  #my( $page, $response, %reply_headers) = https_get(
+  #  'host' => $self->machine,
+  #);
+
+  my $ua = LWP::UserAgent->new;
+  #my $response = $ua->$method(
+  #  $url, \%data,
+  #  'Content-Type'=>'application/x-www-form-urlencoded'
+  #);
+  my $req = HTTP::Request::Common::GET( $url );
+  my $response = $ua->request($req);
+
+  die $response->error_as_HTML if $response->is_error;
+
+  my $page = $response->content;
+
+  my $data = XMLin( $page );
+
+  warn Dumper($data) if $DEBUG;
+
+#  if ( $opt{'areacode'} && $opt{'exchange'} ) { #return numbers
+#
+#    [ map $_->{'number'}, @{ $data->{'item'} } ];
+#
+#  } elsif ( $opt{'areacode'} ) {
+#
+#    [ map $_->{'region'}, @{ $data->{'item'} } ];
+#
+#  } elsif ( $opt{'state'} ) { #return areacodes
+#
+#    [ map $_->{'npa'}, @{ $data->{'item'} } ];
+
+  #if ( $opt{'state'} && $opt{'region'} ) { #return numbers
+  if ( $opt{'region'} ) { #return numbers
+
+    [ map { $_ =~ /^(\d?)(\d{3})(\d{3})(\d{4})$/
+              ? ($1 ? "$1 " : ''). "$2 $3 $4"
+              : $_;
+          }
+        sort { $a <=> $b }
+          map $_->{'phone'},
+            @{ $data->{'item'} }
+    ];
+
+  } elsif ( $opt{'state'} ) { #return regions
+
+    #[ map $_->{'region'}, @{ $data->{'item'} } ];
+    my %regions = map { $_ => 1 } map $_->{'region'}, @{ $data->{'item'} };
+    [ sort keys %regions ];
+
+  #} else { #nothing passed, return states (provinces)
+    # not really needed, we maintain our own list of provinces, but would
+    #  help to hide the ones without availability (need to fix the selector too)
+  }
+
+
+}
+
+#insert, delete, etc... handled with shellcommands
+
+sub _export_insert {
+  #my( $self, $svc_phone ) = (shift, shift);
+}
+sub _export_delete {
+  #my( $self, $svc_phone ) = (shift, shift);
+}
+
+sub _export_replace  { ''; }
+sub _export_suspend  { ''; }
+sub _export_unsuspend  { ''; }
+
+1;
diff --git a/FS/FS/part_export/vitelity.pm b/FS/FS/part_export/vitelity.pm
index 350a5ad..3c0534f 100644
--- a/FS/FS/part_export/vitelity.pm
+++ b/FS/FS/part_export/vitelity.pm
@@ -39,6 +39,8 @@ END
 
 sub rebless { shift; }
 
+sub get_dids_can_tollfree { 1; };
+
 sub get_dids {
   my $self = shift;
   my %opt = ref($_[0]) ? %{$_[0]} : @_;
diff --git a/httemplate/elements/select-did.html b/httemplate/elements/select-did.html
index a69450c..6e205d8 100644
--- a/httemplate/elements/select-did.html
+++ b/httemplate/elements/select-did.html
@@ -16,8 +16,10 @@ Example:
 %   if ( $export->option('restrict_selection') eq 'non-tollfree'
 %		    || !$export->option('restrict_selection') ) {
     <TABLE>
-
       <TR>
+
+%       if ( $export->get_dids_npa_select ) {
+
         <TD VALIGN="top">
           <% include('/elements/select-state.html',
                        'prefix'        => 'phonenum_', #$field.'_',
@@ -29,40 +31,73 @@ Example:
           %>
           <BR><FONT SIZE="-1">State</FONT>
         </TD>
+
+          <TD VALIGN="top">
+            <% include('/elements/select-areacode.html',
+                         'state_prefix' => 'phonenum_', #$field.'_',
+                         'svcpart'      => $svcpart,
+                         'empty'        => 'Select area code',
+                      )
+            %>
+            <BR><FONT SIZE="-1">Area code</FONT>
+          </TD>
+
+          <TD VALIGN="top">
+            <% include('/elements/select-exchange.html',
+                         'svcpart' => $svcpart,
+                         'empty'   => 'Select exchange',
+                      )
+            %>
+            <BR><FONT SIZE="-1">City / Exchange</FONT>
+          </TD>
+
+%       } else {
+
         <TD VALIGN="top">
-          <% include('/elements/select-areacode.html',
-                       'state_prefix' => 'phonenum_', #$field.'_',
-                       'svcpart'      => $svcpart,
-                       'empty'        => 'Select area code',
-                    )
-          %>
-          <BR><FONT SIZE="-1">Area code</FONT>
-        </TD>
-        <TD VALIGN="top">
-          <% include('/elements/select-exchange.html',
-                       'svcpart' => $svcpart,
-                       'empty'   => 'Select exchange',
+          <% include('/elements/select.html',
+                       'field'    => 'phonenum_state',
+                       'id'       => 'phonenum_state',
+                       'options'  => [ '', @{ $export->get_dids } ],
+                       'labels'   => { '' => 'Select province' },
+                       'onchange' => 'phonenum_state_changed(this);',
                     )
           %>
-          <BR><FONT SIZE="-1">City / Exchange</FONT>
+          <BR><FONT SIZE="-1">Province</FONT>
         </TD>
+
+          <TD VALIGN="top">
+            <% include('/elements/select-region.html',
+                         'state_prefix'  => 'phonenum_', #$field.'_',
+                         'svcpart'       => $svcpart,
+                         'empty'         => 'Select region',
+                      )
+            %>
+            <BR><FONT SIZE="-1">Region</FONT>
+          </TD>
+
+%       }
+
         <TD VALIGN="top">
           <% include('/elements/select-phonenum.html',
                        'svcpart'  => $svcpart,
                        'empty'    => 'Select phone number',
 		       'bulknum'  => $bulknum,
                        'multiple' => $multiple,
+                       'region'   => ! $export->get_dids_npa_select,
                     )
           %>
           <BR><FONT SIZE="-1">Phone number</FONT>
         </TD>
-      </TR>
 
+      </TR>
     </TABLE>
 
 % } 
-%   if ( $export->option('restrict_selection') eq 'tollfree'
-%		    || !$export->option('restrict_selection') ) {
+%   if (     ( $export->option('restrict_selection') eq 'tollfree'
+%                || !$export->option('restrict_selection')
+%            )
+%        and $export->get_dids_can_tollfree
+%      ) {
 	    <font size="-1">Toll-free</font>
 	    <% include('/elements/select-phonenum.html',
                        'svcpart' => $svcpart,
diff --git a/httemplate/elements/select-phonenum.html b/httemplate/elements/select-phonenum.html
index d555bf4..18abe3d 100644
--- a/httemplate/elements/select-phonenum.html
+++ b/httemplate/elements/select-phonenum.html
@@ -12,7 +12,7 @@
     what.options[length] = optionName;
   }
 
-  function <% $opt{'prefix'} %>exchange_changed(what, callback) {
+  function <% $opt{'prefix'} %><% $previous %>_changed(what, callback) {
 
     what.form.<% $opt{'prefix'} %>phonenum.disabled = 'disabled';
     what.form.<% $opt{'prefix'} %>phonenum.style.display = 'none';
@@ -21,7 +21,7 @@
     var phonenumerror = document.getElementById('<% $opt{'prefix'} %>phonenumerror');
     phonenumerror.style.display = 'none';
 
-    exchange = what.options[what.selectedIndex].value;
+    var thing = "<% $previous eq 'region' ? '_REGION ' : '' %>" + what.options[what.selectedIndex].value;
 
     function <% $opt{'prefix'} %>update_phonenums(phonenums) {
 
@@ -84,7 +84,7 @@
     }
 
     // go get the new phonenums
-    <% $opt{'prefix'} %>get_phonenums( exchange, <% $opt{'svcpart'} %>, <% $opt{'prefix'} %>update_phonenums );
+    <% $opt{'prefix'} %>get_phonenums( thing, <% $opt{'svcpart'} %>, <% $opt{'prefix'} %>update_phonenums );
 
   }
 
@@ -126,7 +126,7 @@
 % unless ( $opt{'tollfree'} ) {
 <DIV ID="phonenumwait" STYLE="display:none"><IMG SRC="<%$fsurl%>images/wait-orange.gif"> <B>Finding phone numbers</B></DIV>
 
-<DIV ID="phonenumerror" STYLE="display:none"><IMG SRC="<%$fsurl%>images/cross.png"> <B>Select a different city/exchange</B></DIV>
+<DIV ID="phonenumerror" STYLE="display:none"><IMG SRC="<%$fsurl%>images/cross.png"> <B>Select a different <% $opt{'region'} ? 'region' : 'city/exchange' %></B></DIV>
 % }
 
 <SELECT <% $opt{multiple} ? 'MULTIPLE SIZE=25' : '' %>
@@ -146,4 +146,6 @@ my %opt = @_;
 
 $opt{disabled} = 'disabled' unless exists $opt{disabled};
 
+my $previous = $opt{'region'} ? 'region' : 'exchange';
+
 </%init>
diff --git a/httemplate/elements/select-region.html b/httemplate/elements/select-region.html
new file mode 100644
index 0000000..9823290
--- /dev/null
+++ b/httemplate/elements/select-region.html
@@ -0,0 +1,88 @@
+<% include('/elements/xmlhttp.html',
+              'url'  => $p.'misc/regions.cgi',
+              'subs' => [ $opt{'prefix'}. 'get_regions' ],
+          )
+%>
+
+<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 <% $opt{'state_prefix'} %>state_changed(what, callback) {
+
+    what.form.<% $opt{'prefix'} %>region.disabled = 'disabled';
+    what.form.<% $opt{'prefix'} %>region.style.display = 'none';
+    var regionwait = document.getElementById('<% $opt{'prefix'} %>regionwait');
+    regionwait.style.display = '';
+    var regionerror = document.getElementById('<% $opt{'prefix'} %>regionerror');
+    regionerror.style.display = 'none';
+
+    what.form.<% $opt{'prefix'} %>phonenum.disabled = 'disabled';
+
+    state = what.options[what.selectedIndex].value;
+
+    function <% $opt{'prefix'} %>update_regions(regions) {
+
+      // blank the current region
+      for ( var i = what.form.<% $opt{'prefix'} %>region.length; i >= 0; i-- )
+          what.form.<% $opt{'prefix'} %>region.options[i] = null;
+      // blank the current phonenum too
+      for ( var i = what.form.<% $opt{'prefix'} %>phonenum.length; i >= 0; i-- )
+          what.form.<% $opt{'prefix'} %>phonenum.options[i] = null;
+      if ( what.form.<% $opt{'prefix'} %>phonenum.type != 'select-multiple' ) {
+        opt(what.form.<% $opt{'prefix'} %>phonenum, '', 'Select phone number');
+      }
+
+%     if ($opt{empty}) {
+        opt(what.form.<% $opt{'prefix'} %>region, '', '<% $opt{empty} %>');
+%     }
+
+      // add the new regions
+      var regionArray = eval('(' + regions + ')' );
+      for ( var s = 0; s < regionArray.length; s++ ) {
+          var regionLabel = regionArray[s];
+          if ( regionLabel == "" )
+              regionLabel = '(n/a)';
+          opt(what.form.<% $opt{'prefix'} %>region, regionArray[s], regionLabel);
+      }
+
+      regionwait.style.display = 'none';
+      if ( regionArray.length >= 1 ) {
+        what.form.<% $opt{'prefix'} %>region.disabled = '';
+        what.form.<% $opt{'prefix'} %>region.style.display = '';
+      } else {
+        var regionerror = document.getElementById('<% $opt{'prefix'} %>regionerror');
+        regionerror.style.display = '';
+      }
+
+      //run the callback
+      if ( callback != null ) 
+        callback();
+    }
+
+    // go get the new regions
+    <% $opt{'prefix'} %>get_regions( state, <% $opt{'svcpart'} %>, <% $opt{'prefix'} %>update_regions );
+
+  }
+
+</SCRIPT>
+
+<DIV ID="<% $opt{'prefix'} %>regionwait" STYLE="display:none"><IMG SRC="<%$fsurl%>images/wait-orange.gif"> <B>Finding regions</B></DIV>
+
+<DIV ID="<% $opt{'prefix'} %>regionerror" STYLE="display:none"><IMG SRC="<%$fsurl%>images/cross.png"> <B>Select a different state</B></DIV>
+
+<SELECT NAME="<% $opt{'prefix'} %>region" onChange="<% $opt{'prefix'} %>region_changed(this); <% $opt{'onchange'} %>" <% $opt{'disabled'} %>>
+  <OPTION VALUE="">Select region</OPTION>
+</SELECT>
+
+<%init>
+
+my %opt = @_;
+
+$opt{disabled} = 'disabled' unless exists $opt{disabled};
+
+</%init>
diff --git a/httemplate/misc/phonenums.cgi b/httemplate/misc/phonenums.cgi
index fd5de2a..5084628 100644
--- a/httemplate/misc/phonenums.cgi
+++ b/httemplate/misc/phonenums.cgi
@@ -21,13 +21,13 @@ if ( $exchangestring ) {
   my %opts = ();
   if ( $exchangestring eq 'tollfree' ) {
       $opts{'tollfree'} = 1;
-  }
-  #elsif ( $exchangestring =~ /^([\w\s\:\,\(\)\-]+), ([A-Z][A-Z])$/ ) {
-  elsif ( $exchangestring =~ /^(.+), ([A-Z][A-Z])$/ ) {
+  } elsif ( $exchangestring =~ /^_REGION (.*)$/ ) {
+      $opts{'region'} = $1;
+  #} elsif ( $exchangestring =~ /^([\w\s\:\,\(\)\-]+), ([A-Z][A-Z])$/ ) {
+  } elsif ( $exchangestring =~ /^(.+), ([A-Z][A-Z])$/ ) {
       $opts{'ratecenter'} = $1;
       $opts{'state'} = $2;
-  }
-  else {
+  } else {
       $exchangestring =~ /\((\d{3})-(\d{3})-XXXX\)\s*$/i
         or die "unparsable exchange: $exchangestring";
       my( $areacode, $exchange ) = ( $1, $2 );
diff --git a/httemplate/misc/regions.cgi b/httemplate/misc/regions.cgi
new file mode 100644
index 0000000..2450ea3
--- /dev/null
+++ b/httemplate/misc/regions.cgi
@@ -0,0 +1,26 @@
+<% objToJson(\@regions) %>
+<%init>
+
+my( $state, $svcpart ) = $cgi->param('arg');
+
+my $part_svc = qsearchs('part_svc', { 'svcpart'=>$svcpart } );
+die "unknown svcpart $svcpart" unless $part_svc;
+
+my @regions = ();
+if ( $state ) {
+
+  my @exports = $part_svc->part_export_did;
+  if ( scalar(@exports) > 1 ) {
+    die "more than one DID-providing export attached to svcpart $svcpart";
+  } elsif ( ! @exports ) {
+    die "no DID providing export attached to svcpart $svcpart";
+  }
+  my $export = $exports[0];
+
+  my $something = $export->get_dids('state'=>$state);
+
+  @regions = @{ $something };
+
+}
+
+</%init>

-----------------------------------------------------------------------

Summary of changes:
 FS/FS/part_export.pm                           |    4 +
 FS/FS/part_export/fibernetics_did.pm           |  176 ++++++++++++++++++++++++
 FS/FS/part_export/vitelity.pm                  |    2 +
 httemplate/elements/select-did.html            |   69 +++++++---
 httemplate/elements/select-phonenum.html       |   10 +-
 httemplate/elements/select-region.html         |   88 ++++++++++++
 httemplate/misc/phonenums.cgi                  |   10 +-
 httemplate/misc/{areacodes.cgi => regions.cgi} |    6 +-
 8 files changed, 336 insertions(+), 29 deletions(-)
 create mode 100644 FS/FS/part_export/fibernetics_did.pm
 create mode 100644 httemplate/elements/select-region.html
 copy httemplate/misc/{areacodes.cgi => regions.cgi} (86%)




More information about the freeside-commits mailing list