diff options
| -rw-r--r-- | FS/FS/part_export.pm | 4 | ||||
| -rw-r--r-- | FS/FS/part_export/fibernetics_did.pm | 176 | ||||
| -rw-r--r-- | FS/FS/part_export/vitelity.pm | 2 | ||||
| -rw-r--r-- | httemplate/elements/select-did.html | 69 | ||||
| -rw-r--r-- | httemplate/elements/select-phonenum.html | 10 | ||||
| -rw-r--r-- | httemplate/elements/select-region.html | 88 | ||||
| -rw-r--r-- | httemplate/misc/phonenums.cgi | 10 | ||||
| -rw-r--r-- | httemplate/misc/regions.cgi | 26 | 
8 files changed, 359 insertions, 26 deletions
diff --git a/FS/FS/part_export.pm b/FS/FS/part_export.pm index 6768f12d6..93be31c9f 100644 --- a/FS/FS/part_export.pm +++ b/FS/FS/part_export.pm @@ -430,6 +430,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 000000000..76391e88b --- /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 12c3a7fce..83015c7cb 100644 --- a/FS/FS/part_export/vitelity.pm +++ b/FS/FS/part_export/vitelity.pm @@ -38,6 +38,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 a69450c2a..6e205d8ff 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 d555bf4b6..18abe3dea 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 000000000..9823290db --- /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 fd5de2ae6..5084628eb 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 000000000..2450ea31a --- /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>  | 
