From: Christopher Burger Date: Fri, 27 Jul 2018 12:05:10 +0000 (-0400) Subject: RT# 78356 - added speed test fields for broadband service and new modifier to get... X-Git-Url: http://git.freeside.biz/gitweb/?p=freeside.git;a=commitdiff_plain;h=25efd7207d9ea9be4bea1093917c0d8dc4b1e87a RT# 78356 - added speed test fields for broadband service and new modifier to get speed from fcc_477 form in package --- diff --git a/FS/FS/Schema.pm b/FS/FS/Schema.pm index e2c575eb5..0ada39fed 100644 --- a/FS/FS/Schema.pm +++ b/FS/FS/Schema.pm @@ -4890,6 +4890,9 @@ sub tables_hashref { 'suid', 'int', 'NULL', '', '', '', 'shared_svcnum', 'int', 'NULL', '', '', '', 'serviceid', 'varchar', 'NULL', 64, '', '',#srvexport/reportfields + 'speed_test_up', 'int', 'NULL', '', '', '', + 'speed_test_down', 'int', 'NULL', '', '', '', + 'speed_test_latency', 'int', 'NULL', '', '', '', ], 'primary_key' => 'svcnum', 'unique' => [ [ 'ip_addr' ], [ 'mac_addr' ] ], diff --git a/FS/FS/cust_pkg.pm b/FS/FS/cust_pkg.pm index d00f0397b..f29ab9fc0 100644 --- a/FS/FS/cust_pkg.pm +++ b/FS/FS/cust_pkg.pm @@ -5463,6 +5463,24 @@ sub fcc_477_count { } +=item fcc_477_record + +Returns a fcc_477 record based on option name. + +=cut + +sub fcc_477_record { + my ($self, $option_name) = @_; + + my $fcc_record = qsearchs({ + 'table' => 'part_pkg_fcc_option', + 'hashref' => { 'pkgpart' => $self->{Hash}->{pkgpart}, 'fccoptionname' => $option_name, }, + }); + + return ( $fcc_record ); + +} + =item tax_locationnum_sql Returns an SQL expression for the tax location for a package, based diff --git a/FS/FS/part_export/saisei.pm b/FS/FS/part_export/saisei.pm index 2fc112744..617a73226 100644 --- a/FS/FS/part_export/saisei.pm +++ b/FS/FS/part_export/saisei.pm @@ -128,9 +128,7 @@ END sub _export_insert { my ($self, $svc_broadband) = @_; - my $service_part = FS::Record::qsearchs( 'part_svc', { 'svcpart' => $svc_broadband->{Hash}->{svcpart} } ); - my $rateplan_name = $service_part->{Hash}->{svc}; - $rateplan_name =~ s/\s/_/g; + my $rateplan_name = $self->get_rateplan_name($svc_broadband); # check for existing rate plan my $existing_rateplan; @@ -217,15 +215,15 @@ sub _export_insert { sub _export_replace { my ($self, $svc_broadband) = @_; + $self->_export_insert($svc_broadband); return ''; } sub _export_delete { my ($self, $svc_broadband) = @_; - my $service_part = FS::Record::qsearchs( 'part_svc', { 'svcpart' => $svc_broadband->{Hash}->{svcpart} } ); - my $rateplan_name = $service_part->{Hash}->{svc}; - $rateplan_name =~ s/\s/_/g; + my $rateplan_name = $self->get_rateplan_name($svc_broadband); + my $username = $svc_broadband->{Hash}->{svcnum}; ## untie host to user @@ -247,25 +245,49 @@ sub _export_unsuspend { sub export_partsvc { my ($self, $svc_part) = @_; - my $rateplan_name = $svc_part->{Hash}->{svc}; - $rateplan_name =~ s/\s/_/g; - my $speeddown = $svc_part->{Hash}->{svc_broadband__speed_down}; - my $speedup = $svc_part->{Hash}->{svc_broadband__speed_up}; + my $fcc_477_speeds; + if ($svc_part->{Hash}->{svc_broadband__speed_down} eq "down" || $svc_part->{Hash}->{svc_broadband__speed_up} eq "up") { + for my $type (qw( down up )) { + my $speed_type = "broadband_".$type."stream"; + foreach my $pkg_svc (FS::Record::qsearch({ + 'table' => 'pkg_svc', + 'select' => 'pkg_svc.*, part_pkg_fcc_option.fccoptionname, part_pkg_fcc_option.optionvalue', + 'addl_from' => ' LEFT JOIN part_pkg_fcc_option USING (pkgpart) ', + 'extra_sql' => " WHERE pkg_svc.svcpart = ".$svc_part->{Hash}->{svcpart}." AND pkg_svc.quantity > 0 AND part_pkg_fcc_option.fccoptionname = '".$speed_type."'", + })) { $fcc_477_speeds->{ + $pkg_svc->{Hash}->{pkgpart}}->{$speed_type} = $pkg_svc->{Hash}->{optionvalue} * 1000 unless !$pkg_svc->{Hash}->{optionvalue}; } + } + } + else { + $fcc_477_speeds->{1}->{broadband_downstream} = $svc_part->{Hash}->{"svc_broadband__speed_down"}; + $fcc_477_speeds->{1}->{broadband_upstream} = $svc_part->{Hash}->{"svc_broadband__speed_up"}; + } - my $temp_svc = $svc_part->{Hash}; - my $svc_broadband = {}; - map { if ($_ =~ /^svc_broadband__(.*)$/) { $svc_broadband->{Hash}->{$1} = $temp_svc->{$_}; } } keys %$temp_svc; + foreach my $key (keys %$fcc_477_speeds) { - # check for existing rate plan - my $existing_rateplan; - $existing_rateplan = $self->api_get_rateplan($rateplan_name) unless $self->{'__saisei_error'}; + $svc_part->{Hash}->{speed_down} = $fcc_477_speeds->{$key}->{broadband_downstream}; + $svc_part->{Hash}->{speed_up} = $fcc_477_speeds->{$key}->{broadband_upstream}; + $svc_part->{Hash}->{svc_broadband__speed_down} = $fcc_477_speeds->{$key}->{broadband_downstream}; + $svc_part->{Hash}->{svc_broadband__speed_up} = $fcc_477_speeds->{$key}->{broadband_upstream}; - # Modify the existing rate plan with new service data. - $self->api_modify_existing_rateplan($svc_broadband, $rateplan_name) unless ($self->{'__saisei_error'} || !$existing_rateplan); + my $temp_svc = $svc_part->{Hash}; + my $svc_broadband = {}; + map { if ($_ =~ /^svc_broadband__(.*)$/) { $svc_broadband->{Hash}->{$1} = $temp_svc->{$_}; } } keys %$temp_svc; - # if no existing rate plan create one and modify it. - $self->api_create_rateplan($svc_broadband, $rateplan_name) unless $existing_rateplan; - $self->api_modify_rateplan($svc_part, $rateplan_name) unless ($self->{'__saisei_error'} || $existing_rateplan); + my $rateplan_name = $self->get_rateplan_name($svc_broadband, $svc_part->{Hash}->{svc}); + + # check for existing rate plan + my $existing_rateplan; + $existing_rateplan = $self->api_get_rateplan($rateplan_name) unless $self->{'__saisei_error'}; + + # Modify the existing rate plan with new service data. + $self->api_modify_existing_rateplan($svc_broadband, $rateplan_name) unless ($self->{'__saisei_error'} || !$existing_rateplan); + + # if no existing rate plan create one and modify it. + $self->api_create_rateplan($svc_broadband, $rateplan_name) unless $existing_rateplan; + $self->api_modify_rateplan($svc_part, $rateplan_name) unless ($self->{'__saisei_error'} || $existing_rateplan); + + } return $self->api_error; @@ -310,6 +332,19 @@ sub export_tower_sector { return $self->api_error; } +## creates the rateplan name +sub get_rateplan_name { + my ($self, $svc_broadband, $svc_name) = @_; + + my $service_part = FS::Record::qsearchs( 'part_svc', { 'svcpart' => $svc_broadband->{Hash}->{svcpart} } ) unless $svc_name; + my $service_name = $svc_name ? $svc_name : $service_part->{Hash}->{svc}; + + my $rateplan_name = $service_name . " " . $svc_broadband->{Hash}->{speed_down} . "-" . $svc_broadband->{Hash}->{speed_up}; + $rateplan_name =~ s/\s/_/g; + + return $rateplan_name; +} + =head1 Saisei API These methods allow access to the Saisei API using the credentials diff --git a/FS/FS/part_svc.pm b/FS/FS/part_svc.pm index 341559594..b82996e0d 100644 --- a/FS/FS/part_svc.pm +++ b/FS/FS/part_svc.pm @@ -873,10 +873,10 @@ sub process { map { my $f = $svcdb.'__'.$_; my $flag = $param->{ $f.'_flag' } || ''; #silence warnings - if ( $flag =~ /^[MAH]$/ ) { + if ( $flag =~ /^[MAHP]$/ ) { $param->{ $f } = delete( $param->{ $f.'_classnum' } ); } - if ( ( $flag =~ /^[MAHS]$/ or $_ eq 'usergroup' ) + if ( ( $flag =~ /^[MAHSP]$/ or $_ eq 'usergroup' ) and ref($param->{ $f }) ) { $param->{ $f } = join(',', @{ $param->{ $f } }); } diff --git a/FS/FS/part_svc_column.pm b/FS/FS/part_svc_column.pm index 75a2dfb1a..e055af35a 100644 --- a/FS/FS/part_svc_column.pm +++ b/FS/FS/part_svc_column.pm @@ -97,7 +97,7 @@ sub check { ; return $error if $error; - $self->columnflag =~ /^([DFSMAHX]?)$/ + $self->columnflag =~ /^([DFSMAHXP]?)$/ or return "illegal columnflag ". $self->columnflag; $self->columnflag(uc($1)); diff --git a/FS/FS/svc_broadband.pm b/FS/FS/svc_broadband.pm index b8b1a6eab..bd7bf9b13 100755 --- a/FS/FS/svc_broadband.pm +++ b/FS/FS/svc_broadband.pm @@ -107,8 +107,16 @@ sub table_info { 'fields' => { 'svcnum' => 'Service', 'description' => 'Descriptive label', - 'speed_down' => 'Download speed (Kbps)', - 'speed_up' => 'Upload speed (Kbps)', + 'speed_up' => { + 'label' => 'Upload speed (Kbps)', + 'type' => 'fcc_477_speed', + 'def_info' => 'both upload and download speed must be set to FCC 477 information if using that modifier', + }, + 'speed_down' => { + 'label' => 'Download speed (Kbps)', + 'type' => 'fcc_477_speed', + 'def_info' => 'both upload and download speed must be set to FCC 477 information if using that modifier', + }, 'ip_addr' => 'IP address', 'blocknum' => { 'label' => 'Address block', @@ -148,6 +156,9 @@ sub table_info { disable_inventory => 1, }, 'serviceid' => 'Torrus serviceid', #but is should be hidden + 'speed_test_up' => 'Speed test download (Kbps)', + 'speed_test_down' => 'Speed test upload (Kbps)', + 'speed_test_latency' => 'Speed test latency (ms)', }, }; } diff --git a/httemplate/browse/part_svc.cgi b/httemplate/browse/part_svc.cgi index b9474636d..222433db3 100755 --- a/httemplate/browse/part_svc.cgi +++ b/httemplate/browse/part_svc.cgi @@ -251,6 +251,7 @@ my %flag = ( 'A' => 'Automatically filled in from inventory', 'H' => 'Selected from hardware class', 'X' => 'Excluded', + 'P' => 'From package 477 information', ); my %search; diff --git a/httemplate/edit/elements/part_svc_column.html b/httemplate/edit/elements/part_svc_column.html index 816f3428b..bdbce7c79 100644 --- a/httemplate/edit/elements/part_svc_column.html +++ b/httemplate/edit/elements/part_svc_column.html @@ -15,6 +15,7 @@ To be called from part_svc.cgi. # don't allow the 'inventory' flags (M, A) to be chosen for # fields that aren't free-text my $inv_sub = sub { $_[0]->{disable_inventory} || $_[0]->{type} ne 'text' }; + tie my %flag, 'Tie::IxHash', '' => { 'desc' => 'No default', 'condition' => sub { 0 } }, 'D' => { 'desc' => 'Default', @@ -38,6 +39,9 @@ tie my %flag, 'Tie::IxHash', 'H' => { 'desc' => 'Select from hardware class', 'condition' => sub { $_[0]->{type} ne 'select-hardware' }, }, + 'P' => { 'desc' => 'From package FCC 477 information', + 'condition' => sub { $_[0]->{type} ne 'fcc_477_speed' }, # get values from package fcc 477 information + }, 'X' => { 'desc' => 'Excluded', 'condition' => sub { 1 }, # obsolete }, @@ -202,6 +206,20 @@ my %communigate_fields = ( % $mode = 'hardware'; % $multiple = 0; % } +% +% if ( $def->{'type'} eq 'fcc_477_speed' ) { +% if ($field eq 'speed_up') { + + upstream speed + + +% } elsif ($field eq 'speed_down') { + + downstream speed + + +% } +% } else { <& /elements/select-table.html, 'field' => $name.'_classnum', 'id' => $name.'_select', @@ -211,6 +229,7 @@ my %communigate_fields = ( 'empty_label' => "Select $mode class", 'multiple' => $multiple, &> +% } % } diff --git a/httemplate/edit/elements/svc_Common.html b/httemplate/edit/elements/svc_Common.html index a4e345e40..e1c309080 100644 --- a/httemplate/edit/elements/svc_Common.html +++ b/httemplate/edit/elements/svc_Common.html @@ -169,6 +169,16 @@ ]; } # shouldn't this be enforced for all 'S' fields? + elsif ( $flag eq 'P' ) { #form fcc_477 values + $f->{type} = 'fixed'; + my $cust_pkg = FS::Record::qsearchs({ + 'table' => 'cust_pkg', + 'hashref' => { 'pkgnum' => $object->{Hash}->{pkgnum} } + }); + my $fcc_record = $cust_pkg->fcc_477_record('broadband_'.$columndef->columnvalue.'stream') if $cust_pkg; + $f->{'value'} = $fcc_record->{Hash}->{optionvalue} ? $fcc_record->{Hash}->{optionvalue} * 1000 : ''; + } # end 477 values + if ( $f->{'type'} =~ /^select-svc/ ) { $f->{'include_opt_callback'} = diff --git a/httemplate/edit/part_svc.cgi b/httemplate/edit/part_svc.cgi index fed21256f..49c1c03d8 100755 --- a/httemplate/edit/part_svc.cgi +++ b/httemplate/edit/part_svc.cgi @@ -107,7 +107,7 @@ function flag_changed(obj) { select.multiple = false; } } - } else if ( newflag == 'M' || newflag == 'A' || newflag == 'H' ) { + } else if ( newflag == 'M' || newflag == 'A' || newflag == 'H' || newflag == 'P' ) { // these all require a class selection if ( select ) { select.disabled = false; @@ -120,7 +120,7 @@ function flag_changed(obj) { } var required = document.getElementById(layer + '__' + field + '_required'); if (required && !required.disabledinit) { - if (newflag == "F") { + if (newflag == "F" || newflag =="P") { required.checked = false; required.disabled = true; } else { diff --git a/httemplate/edit/process/elements/process.html b/httemplate/edit/process/elements/process.html index 8c307f0b6..c197eb123 100644 --- a/httemplate/edit/process/elements/process.html +++ b/httemplate/edit/process/elements/process.html @@ -89,6 +89,9 @@ Example: # for use with tables that are FS::option_Common (among other things) 'args_callback' => sub { my( $cgi, $object ) = @_; }, + # if no errors after package insert or replace will update services attached to package. + 'update_svc' => sub { my( $cgi, $object ) = @_; }, + 'debug' => 1, #turns on debugging output #agent virtualization @@ -438,6 +441,12 @@ foreach my $value ( @values ) { } } + if ( !$error and $opt{'update_svc'} ) { + my @args = (); + @args = &{ $opt{'args_callback'} }( $cgi, $new ) if $opt{'args_callback'}; + $error = &{ $opt{'update_svc'} }( $cgi, $new, @args ); + } + if ( $error ) { $cgi->param('error', $error); diff --git a/httemplate/edit/process/part_pkg.cgi b/httemplate/edit/process/part_pkg.cgi index c4d150ba1..6bab20278 100755 --- a/httemplate/edit/process/part_pkg.cgi +++ b/httemplate/edit/process/part_pkg.cgi @@ -9,6 +9,7 @@ 'edit_ext' => 'cgi', 'precheck_callback' => $precheck_callback, 'args_callback' => $args_callback, + 'update_svc' => $update_svc, 'process_locale' => 'pkg', 'process_m2m' => \@process_m2m, 'process_o2m' => \@process_o2m, @@ -199,6 +200,37 @@ my $args_callback = sub { }; +## update services upon package change. +my $update_svc = sub { + my $cgi = shift @_; + my $new = shift @_; + my %args = @_; + my $error; + + my @svcs = $new->pkg_svc(); + + foreach my $svc_part(@svcs) { + my @part_svc_column = qsearch('part_svc_column',{ 'svcpart' => $svc_part->{Hash}->{svcpart}, 'columnflag' => 'P' }); + + if ($svc_part->{Hash}->{svcdb} eq "svc_broadband" && (keys $args{fcc_options}) && @part_svc_column ) { + ## find provisioned services to update + my @svc_svcdb = qsearch({ + 'table' => 'svc_broadband', + 'select' => 'svc_broadband.*, cust_svc.svcpart', + 'addl_from' => 'LEFT JOIN cust_svc USING (svcnum) LEFT JOIN cust_pkg USING (pkgnum)', + 'extra_sql' => " WHERE cust_svc.svcpart = '".$svc_part->{Hash}->{svcpart}."' AND cust_pkg.pkgpart = '".$svc_part->{Hash}->{pkgpart}."'", + }); + foreach my $svc (@svc_svcdb) { + #my $svc_new = $svc; + $svc->{Hash}->{speed_down} = $args{fcc_options}->{broadband_downstream} * 1000; + $svc->{Hash}->{speed_up} = $args{fcc_options}->{broadband_upstream} * 1000; + $error = $svc->replace(); + } + } + } + return $error; +}; + my $redirect_callback = sub { #my( $cgi, $new ) = @_; return '' unless $custnum; diff --git a/httemplate/edit/svc_broadband.cgi b/httemplate/edit/svc_broadband.cgi index 81c694aa5..bcf55fe11 100644 --- a/httemplate/edit/svc_broadband.cgi +++ b/httemplate/edit/svc_broadband.cgi @@ -100,7 +100,7 @@ END ; my @fields = ( - qw( description speed_down speed_up ), + qw( description speed_down speed_up speed_test_down speed_test_up speed_test_latency), { field=>'sectornum', type=>'select-tower_sector', }, { field=>'routernum', type=>'select-router_block_ip', include_opt_callback => sub { @@ -179,7 +179,6 @@ my $svc_field_callback = sub { my $columndef = $part_svc->part_svc_column($fieldref->{'field'}); if ($fieldref->{field} eq 'usergroup' && $columndef->columnflag eq 'F') { - $fieldref->{'formatted_value'} = [ $object->radius_groups('long_description') ]; }