Merge branch 'master' of git.freeside.biz:/home/git/freeside
authorIvan Kohler <ivan@freeside.biz>
Wed, 1 Aug 2018 20:34:56 +0000 (13:34 -0700)
committerIvan Kohler <ivan@freeside.biz>
Wed, 1 Aug 2018 20:34:56 +0000 (13:34 -0700)
28 files changed:
FS/FS/Conf.pm
FS/FS/Misc.pm
FS/FS/Schema.pm
FS/FS/Template_Mixin.pm
FS/FS/cust_bill.pm
FS/FS/cust_main/Billing_Realtime.pm
FS/FS/cust_pkg.pm
FS/FS/cust_pkg/Import.pm
FS/FS/msg_template/email.pm
FS/FS/part_export/saisei.pm
FS/FS/part_svc.pm
FS/FS/part_svc_column.pm
FS/FS/svc_broadband.pm
bin/move_svc_broadband_speeds.pl [new file with mode: 0644]
fs_selfservice/FS-SelfService/cgi/card.html
fs_selfservice/FS-SelfService/cgi/selfservice.cgi
httemplate/browse/part_svc.cgi
httemplate/edit/elements/part_svc_column.html
httemplate/edit/elements/svc_Common.html
httemplate/edit/part_svc.cgi
httemplate/edit/process/elements/process.html
httemplate/edit/process/part_pkg.cgi
httemplate/edit/svc_broadband.cgi
httemplate/misc/cust_pkg-import.html
httemplate/search/cust_timespan.html
httemplate/search/elements/search.html
httemplate/search/report_cust_timespan.html
httemplate/view/svc_broadband.cgi

index bd544c9..302bae7 100644 (file)
@@ -789,6 +789,14 @@ my $validate_email = sub { $_[0] =~
   },
 
   {
+    'key'         => 'credit-card-surcharge-text',
+    'section'     => 'credit_cards',
+    'description' => 'Text for the credit card surcharge invoice line.  If not set, it will default to Credit Card Surcharge.',
+    'type'        => 'text',
+    'per_agent'   => 1,
+  },
+
+  {
     'key'         => 'discount-show-always',
     'section'     => 'invoicing',
     'description' => 'Generate a line item on an invoice even when a package is discounted 100%',
index d84aace..fd2c325 100644 (file)
@@ -1,7 +1,7 @@
 package FS::Misc;
 
 use strict;
-use vars qw ( @ISA @EXPORT_OK $DEBUG );
+use vars qw ( @ISA @EXPORT_OK $DEBUG $DISABLE_ALL_NOTICES );
 use Exporter;
 use Carp;
 use Data::Dumper;
@@ -43,6 +43,32 @@ Miscellaneous subroutines.  This module contains miscellaneous subroutines
 called from multiple other modules.  These are not OO or necessarily related,
 but are collected here to eliminate code duplication.
 
+=head1 DISABLE ALL NOTICES
+
+Set $FS::Misc::DISABLE_ALL_NOTICES to suppress:
+
+=over 4
+
+=item FS::cust_bill::send_csv
+
+=item FS::cust_bill::spool_csv
+
+=item FS::msg_template::email::send_prepared
+
+=item FS::Misc::send_email
+
+=item FS::Misc::do_print
+
+=item FS::Misc::send_fax
+
+=item FS::Template_Mixin::postal_mail_fsinc
+
+=back
+
+=cut
+
+$DISABLE_ALL_NOTICES = 0;
+
 =head1 SUBROUTINES
 
 =over 4
@@ -118,6 +144,12 @@ FS::UID->install_callback( sub {
 
 sub send_email {
   my(%options) = @_;
+
+  if ( $DISABLE_ALL_NOTICES ) {
+    warn 'send_email() disabled by $FS::Misc::DISABLE_ALL_NOTICES' if $DEBUG;
+    return;
+  }
+
   if ( $DEBUG ) {
     my %doptions = %options;
     $doptions{'body'} = '(full body not shown in debug)';
@@ -450,6 +482,11 @@ sub send_fax {
   die 'HylaFAX support has not been configured.'
     unless $conf->exists('hylafax');
 
+  if ( $DISABLE_ALL_NOTICES ) {
+    warn 'send_fax() disabled by $FS::Misc::DISABLE_ALL_NOTICES' if $DEBUG;
+    return;
+  }
+
   eval {
     require Fax::Hylafax::Client;
   };
@@ -869,6 +906,11 @@ global value and agentnum).
 sub do_print {
   my( $data, %opt ) = @_;
 
+  if ( $DISABLE_ALL_NOTICES ) {
+    warn 'do_print() disabled by $FS::Misc::DISABLE_ALL_NOTICES' if $DEBUG;
+    return;
+  }
+
   my $lpr = ( exists($opt{'lpr'}) && $opt{'lpr'} )
               ? $opt{'lpr'}
               : $conf->config('lpr', $opt{'agentnum'} );
index d47046f..59a18c5 100644 (file)
@@ -4891,6 +4891,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' ] ],
index 1b3df00..34e9e6e 100644 (file)
@@ -2513,6 +2513,11 @@ use MIME::Base64;
 sub postal_mail_fsinc {
   my ( $self, %opt ) = @_;
 
+  if ( $FS::Misc::DISABLE_PRINT ) {
+    warn 'postal_mail_fsinc() disabled by $FS::Misc::DISABLE_PRINT' if $DEBUG;
+    return;
+  }
+
   my $url = 'https://ws.freeside.biz/print';
 
   my $cust_main = $self->cust_main;
index 0a735f7..47f71c4 100644 (file)
@@ -1405,6 +1405,11 @@ See L</print_csv> for a description of the output format.
 sub send_csv {
   my($self, %opt) = @_;
 
+  if ( $FS::Misc::DISABLE_ALL_NOTICES ) {
+    warn 'send_csv() disabled by $FS::Misc::DISABLE_ALL_NOTICES' if $DEBUG;
+    return;
+  }
+
   #create file(s)
 
   my $spooldir = "/usr/local/etc/freeside/export.". datasrc. "/cust_bill";
@@ -1481,6 +1486,11 @@ in the ICS format.
 sub spool_csv {
   my($self, %opt) = @_;
 
+  if ( $FS::Misc::DISABLE_ALL_NOTICES ) {
+    warn 'spool_csv() disabled by $FS::Misc::DISABLE_ALL_NOTICES' if $DEBUG;
+    return;
+  }
+
   my $time = $opt{'time'} || time;
   my $cust_main = $self->cust_main;
 
index f4d87dd..d286f63 100644 (file)
@@ -1078,9 +1078,11 @@ sub _realtime_bop_result {
          }
 
          my $cust_pkg;
+    my $cc_surcharge_text = 'Credit Card Surcharge';
+    $cc_surcharge_text = $conf->config('credit-card-surcharge-text', $self->agentnum) if $conf->exists('credit-card-surcharge-text', $self->agentnum);
          my $charge_error = $self->charge({
                                    'amount'    => $options{'cc_surcharge'},
-                                   'pkg'       => 'Credit Card Surcharge',
+                                   'pkg'       => $cc_surcharge_text,
                                    'setuptax'  => 'Y',
                                    'cust_pkg_ref' => \$cust_pkg,
                                });
index d00f039..f29ab9f 100644 (file)
@@ -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
index 93bd88d..2b18323 100644 (file)
@@ -102,6 +102,7 @@ my %formatfields = (
   'default'      => [],
   'all_dates'    => [],
   'svc_acct'     => [qw( username _password domsvc )],
+  'svc_broadband' => [qw( ip_addr description routernum blocknum sectornum speed_up speed_down )],
   'svc_phone'    => [qw( countrycode phonenum sip_password pin )],
   'svc_external' => [qw( id title )],
   'location'     => [qw( address1 address2 city state zip country )],
index 37c1fab..c2c3707 100644 (file)
@@ -529,6 +529,11 @@ sub send_prepared {
   my $self = shift;
   my $cust_msg = shift or die "cust_msg required";
 
+  if ( $FS::Misc::DISABLE_ALL_NOTICES ) {
+    warn 'send_prepared() disabled by $FS::Misc::DISABLE_ALL_NOTICES' if $DEBUG;
+    return;
+  }
+
   my $domain = 'example.com';
   if ( $cust_msg->env_from =~ /\@([\w\.\-]+)/ ) {
     $domain = $1;
index 2fc1127..c79f79d 100644 (file)
@@ -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
@@ -795,7 +830,7 @@ sub export_provisioned_services {
   my $svc_count = scalar @svcs;
 
   my %status = {};
-  for (my $c=10; $c <=100; $c=$c+10) { $status{int($svc_count * ($c/100))} = $c; }
+  for (my $c=1; $c <=100; $c=$c+1) { $status{int($svc_count * ($c/100))} = $c; }
 
   my $process_count=0;
   foreach my $svc (@svcs) {
index 3415595..b82996e 100644 (file)
@@ -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 } });
                    }
index 75a2dfb..e055af3 100644 (file)
@@ -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));
 
index b8b1a6e..02136c5 100755 (executable)
@@ -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'      => { 'label' => 'Speed test upload (Kbps)' },
+      'speed_test_down'    => { 'label' => 'Speed test download (Kbps)' },
+      'speed_test_latency' => 'Speed test latency (ms)',
     },
   };
 }
@@ -353,6 +364,8 @@ sub check {
     || $self->ut_textn('description')
     || $self->ut_numbern('speed_up')
     || $self->ut_numbern('speed_down')
+    || $self->ut_numbern('speed_test_up')
+    || $self->ut_numbern('speed_test_down')
     || $self->ut_ipn('ip_addr')
     || $self->ut_hexn('mac_addr')
     || $self->ut_hexn('auth_key')
diff --git a/bin/move_svc_broadband_speeds.pl b/bin/move_svc_broadband_speeds.pl
new file mode 100644 (file)
index 0000000..fed405b
--- /dev/null
@@ -0,0 +1,52 @@
+#!/usr/bin/perl
+
+use strict;
+use FS::UID qw(adminsuidsetup);
+use FS::Record qw(qsearchs qsearch);
+use FS::svc_broadband;
+
+my $user = shift or die &usage;
+my $dbh = adminsuidsetup($user);
+
+my $fcc_up_speed = "(select part_pkg_fcc_option.optionvalue from part_pkg_fcc_option where fccoptionname = 'broadband_upstream' and pkgpart = cust_pkg.pkgpart) AS fcc477_upstream";
+my $fcc_down_speed = "(select part_pkg_fcc_option.optionvalue from part_pkg_fcc_option where fccoptionname = 'broadband_downstream' and pkgpart = cust_pkg.pkgpart) AS fcc477_downstream";
+foreach my $rec (qsearch({
+       'select'    => 'svc_broadband.*, cust_svc.svcpart, cust_pkg.pkgpart, '.$fcc_up_speed.', '.$fcc_down_speed,
+       'table'     => 'svc_broadband',
+       'addl_from' => 'LEFT JOIN cust_svc USING ( svcnum ) LEFT JOIN cust_pkg USING ( pkgnum )',
+})) {
+  $rec->{Hash}->{speed_test_up} = $rec->{Hash}->{speed_up};
+  $rec->{Hash}->{speed_test_down} = $rec->{Hash}->{speed_down};
+  $rec->{Hash}->{speed_up} = $rec->{Hash}->{fcc477_upstream} * 1000;
+  $rec->{Hash}->{speed_down} = $rec->{Hash}->{fcc477_downstream} * 1000;
+  $rec->replace();
+  warn "Fixing broadband service speeds for service ".$rec->{Hash}->{svcnum}."-".$rec->{Hash}->{description}."\n";
+}
+
+warn "Completed fixing broadband service speeds!\n";
+
+exit;
+
+=head1 NAME
+
+move_svc_broadband_speeds
+
+=head1 SYNOPSIS
+
+  move_svc_broadband_speeds.pl [ user ]
+
+=head1 DESCRIPTION
+
+Moves value for speed_down to speed_test_down, speed_up to speed_test_up, 
+and sets speed_down, speed_up to matching fcc_477 speeds from package for
+all svc_broadband services.
+
+user: freeside username
+
+=head1 BUGS
+
+=head1 SEE ALSO
+
+L<FS::svc_broadband>
+
+=cut
\ No newline at end of file
index dfe6371..eb3e061 100644 (file)
@@ -9,7 +9,7 @@
         <TD>
           <SELECT NAME="month">
             <%= for ( ( map "0$_", 1 .. 9 ), 10 .. 12 ) {
-                  $OUT .= '<OPTION'. ($_ == $month ? ' SELECTED' : ''). ">$_\n";
+                  $OUT .= '<OPTION'. ($_ == $month ? ' SELECTED' : ''). " VALUE='$_'>$_\n";
             } %>
           </SELECT>
         </TD>
@@ -17,7 +17,7 @@
         <TD>
           <SELECT NAME="year">
             <%= my @a = localtime; for ( $a[5]+1900 .. $a[5]+1915 ) {
-                  $OUT .= '<OPTION'. ($_ == $year ? ' SELECTED' : ''). ">$_\n";
+                  $OUT .= '<OPTION'. ($_ == $year ? ' SELECTED' : ''). " VALUE='$_'>$_\n";
             } %>
           </SELECT>
         </TD>
index 6cf264c..3dc69e1 100755 (executable)
@@ -726,9 +726,9 @@ sub payment_results {
   $cgi->param('paycvv') =~ /^\s*(.{0,4})\s*$/ or die "illegal CVV2";
   my $paycvv = $1;
 
-  $cgi->param('month') =~ /^(\d{2})$/ or die "illegal month";
+  $cgi->param('month') =~ /^(\d{2})/ or die "illegal month";
   my $month = $1;
-  $cgi->param('year') =~ /^(\d{4})$/ or die "illegal year";
+  $cgi->param('year') =~ /^(\d{4})/ or die "illegal year";
   my $year = $1;
 
   $cgi->param('payname') =~ /^(.{0,80})$/ or die "illegal payname";
@@ -1325,5 +1325,3 @@ sub include {
                     );
 
 }
-
-
index b947463..222433d 100755 (executable)
@@ -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;
index 816f342..bdbce7c 100644 (file)
@@ -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') {
+          <SPAN ID="<% $name %>_select">
+            upstream speed
+            <INPUT TYPE="hidden" ID="<% $name %>_select" NAME="<% $name %>_classnum" VALUE="up">
+          </SPAN>
+%       } elsif ($field eq 'speed_down') {
+          <SPAN ID="<% $name %>_select">
+            downstream speed
+            <INPUT TYPE="hidden" ID="<% $name %>_select" NAME="<% $name %>_classnum" VALUE="down">
+          </SPAN>
+%       }
+%     } 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,
       &>
+%     }
 %   }
     </TD>
     <TD>
index a4e345e..e1c3090 100644 (file)
                                      ];
                    } # 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'} =
index fed2125..49c1c03 100755 (executable)
@@ -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 {
index 8c307f0..c197eb1 100644 (file)
@@ -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);
index c4d150b..5beb034 100755 (executable)
@@ -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,38 @@ 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();
+
+## update broadband services getting their up and down speeds from package fcc_477 options
+  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) {
+        next if ($svc->{Hash}->{speed_down} == $args{fcc_options}->{broadband_downstream} * 1000 && $svc->{Hash}->{speed_up} == $args{fcc_options}->{broadband_upstream} * 1000);
+        $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;
index 81c694a..bcf55fe 100644 (file)
@@ -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') ];
   }
index 6272d28..da242a2 100644 (file)
@@ -36,6 +36,7 @@ Import a file containing customer packages.
         <OPTION VALUE="svc_acct">Account service
         <OPTION VALUE="svc_acct-agent_custid">Account service with agent_custid
         <OPTION VALUE="svc_acct-locationnum">Account service with existing location
+        <OPTION VALUE="svc_broadband">Broadband service
         <OPTION VALUE="svc_phone">Phone service
         <OPTION VALUE="svc_phone-agent_custid">Phone service with agent_custid
         <OPTION VALUE="svc_phone-locationnum">Phone service with existing location
@@ -105,6 +106,9 @@ Uploaded files can be CSV (comma-separated value) files or Excel spreadsheets.
 <b>Account service with existing location</b> format has the following field order: <i>custnum<%$req%>, locationnum, pkgpart<%$req%>, discountnum, start_date, setup, bill, last_bill, susp, adjourn, cancel, expire, username, _password, domsvc</i>
 <BR><BR>
 
+<b>Broadband service</b> format has the following field order: <i>custnum<%$req%>, pkgpart<%$req%>, discountnum, start_date, setup, bill, last_bill, susp, adjourn, cancel, expire, ip_addr<%$req%>, description, routernum, blocknum, sectornum, speed_up, speed_down</i>
+<BR><BR>
+
 <b>Phone service</b> format has the following field order: <i>custnum<%$req%>, pkgpart<%$req%>, discountnum, start_date, setup, bill, last_bill, susp, adjourn, cancel, expire, countrycode, phonenum, sip_password, pin</i>
 <BR><BR>
 
index f568425..f95250a 100644 (file)
@@ -11,6 +11,7 @@
                   'header'      => \@header,
                   'fields'      => \@fields,
                   'links'       => \@links,
+                  'disable_maxselect' => '1',
 
 &>
 <%init>
@@ -84,7 +85,11 @@ my $active_pkg_sql = 'select pkgnum from cust_pkg where cust_pkg.custnum = cust_
 
 ## sql to get the first active date, last cancel date, and last reason.
 my $active_date = 'select min(setup) from cust_pkg left join part_pkg using (pkgpart) where cust_pkg.custnum = cust_main.custnum and part_pkg.freq > \'0\'';
-my $cancel_date = 'select max(cancel) from cust_pkg where cust_pkg.custnum = cust_main.custnum';
+
+## set cancel date range here
+my($beginning_date, $ending_date) = FS::UI::Web::parse_beginning_ending($cgi, '');
+my $cancel_date = 'select max(cancel) from cust_pkg left join part_pkg using (pkgpart) where cust_pkg.custnum = cust_main.custnum and part_pkg.freq > \'0\' and (cancel >= '.$beginning_date.' and cancel <= '.$ending_date.')';
+
 my $cancel_reason = 'select reason.reason from cust_pkg
        left join cust_pkg_reason on (cust_pkg.pkgnum = cust_pkg_reason.pkgnum)
        left join reason on (cust_pkg_reason.reasonnum = reason.reasonnum)
index 0e8c69a..730a51a 100644 (file)
@@ -389,14 +389,15 @@ unless ( $type =~ /^(csv|xml|\w*.xls)$/) {
     #setup some pagination things if we're in html mode
 
     my $conf = new FS::Conf;
-    $confmax = $conf->config('maxsearchrecordsperpage') || 100;
-    if ( $cgi->param('maxrecords') =~ /^(\d+)$/ ) {
-      $maxrecords = $1;
-    } else {
-      $maxrecords ||= $confmax;
-    }
-
     $opt{'disable_maxselect'} ||= $conf->exists('disable_maxselect');
+    unless ($opt{'disable_maxselect'}) {
+      $confmax = $conf->config('maxsearchrecordsperpage') || 100;
+      if ( $cgi->param('maxrecords') =~ /^(\d+)$/ ) {
+        $maxrecords = $1;
+      } else {
+        $maxrecords ||= $confmax;
+      }
+    }
 
     $limit = $maxrecords ? "LIMIT $maxrecords" : '';
 
index 4ff3bb8..27dd940 100644 (file)
@@ -20,6 +20,8 @@
        'curr_value' => scalar( $cgi->param('cust_status') ),
   &>
 
+  <& /elements/tr-input-beginning_ending.html &>
+
 </FORM>
 
 </TABLE>
index 0517c30..189fe5e 100644 (file)
@@ -33,6 +33,9 @@ my @fields = (
   { field => 'routernum', value_callback => \&router },
   'speed_down',
   'speed_up',
+  'speed_test_down',
+  'speed_test_up',
+  'speed_test_latency',
   { field => 'ip_addr', value_callback => \&ip_addr },
   { field => 'sectornum', value_callback => \&sectornum },
   { field => 'mac_addr', type=>'mac_addr', value_callback => \&mac_addr },