Merge branch 'master' of git.freeside.biz:/home/git/freeside
authorIvan Kohler <ivan@freeside.biz>
Tue, 17 Jul 2018 01:43:48 +0000 (18:43 -0700)
committerIvan Kohler <ivan@freeside.biz>
Tue, 17 Jul 2018 01:43:48 +0000 (18:43 -0700)
1  2 
FS/FS/Conf.pm
FS/FS/Upgrade.pm
FS/FS/cust_main/Billing_Batch.pm
FS/FS/svc_IP_Mixin.pm
FS/FS/svc_broadband.pm

diff --combined FS/FS/Conf.pm
@@@ -783,7 -783,7 +783,7 @@@ my $validate_email = sub { $_[0] =
    {
      'key'         => 'credit-card-surcharge-flatfee',
      'section'     => 'credit_cards',
 -    'description' => 'Add a credit card surcharge to invoices, as a flat fee.',
 +    'description' => 'Add a credit card surcharge to invoices, as a flat fee.  WARNING: Although recently permitted to US merchants in general, specific consumer protection laws may prohibit or restrict this practice in California, Colorado, Connecticut, Florda, Kansas, Maine, Massachusetts, New York, Oklahome, and Texas.  Surcharging is also generally prohibited in most countries outside the US, AU and UK.  When allowed, typically not permitted to be above 4%.',
      'type'        => 'text',
      'per_agent'   => 1,
    },
@@@ -2788,6 -2788,13 +2788,13 @@@ and customer address. Include units.'
    },
  
    {
+     'key'         => 'manual_process-single_invoice_amount',
+     'section'     => 'deprecated',
+     'description' => 'When entering manual credit card and ACH payments, amount will not autofill if the customer has more than one open invoice',
+     'type'        => 'checkbox',
+   },
+   {
      'key'         => 'manual_process-pkgpart',
      'section'     => 'payments',
      'description' => 'Package to add to each manual credit card and ACH payment entered by employees from the backend.  WARNING: Although recently permitted to US merchants in general, specific consumer protection laws may prohibit or restrict this practice in California, Colorado, Connecticut, Florda, Kansas, Maine, Massachusetts, New York, Oklahome, and Texas. Surcharging is also generally prohibited in most countries outside the US, AU and UK.',
diff --combined FS/FS/Upgrade.pm
@@@ -338,10 -338,7 +338,10 @@@ sub upgrade 
        });
        foreach my $object ( @objects ) {
            my $payinfo = $object->decrypt($object->payinfo);
 -          die "error decrypting payinfo" if $payinfo eq $object->payinfo;
 +          if ( $payinfo eq $object->payinfo ) {
 +            warn "error decrypting payinfo for $table: $payinfo\n";
 +            next;
 +          }
            $object->payinfo($payinfo);
            my $error = $object->replace;
            die $error if $error;
@@@ -504,6 -501,23 +504,23 @@@ sub upgrade_data 
      #'compliance solutions' -> 'compliance_solutions'
      'tax_rate' => [],
      'tax_rate_location' => [],
+     #upgrade part_event_condition_option agentnum to a multiple hash value
+     'part_event_condition_option' =>[],
+     #fix ip format
+     'svc_circuit' => [],
+     #fix ip format
+     'svc_hardware' => [],
+     #fix ip format
+     'svc_pbx' => [],
+     #fix ip format
+     'tower_sector' => [],
    ;
  
    \%hash;
@@@ -714,4 -728,3 +731,3 @@@ Sure
  =cut
  
  1;
@@@ -114,7 -114,7 +114,7 @@@ sub batch_card 
    } );
  
    foreach (qw( address1 address2 city state zip country latitude longitude
-                payby payinfo paydate payname paycode ))
+                payby payinfo paydate payname paycode paytype ))
    {
      $options{$_} = '' unless exists($options{$_});
    }
      'country'  => $options{country}  || $loc->country,
      'payby'    => $options{payby}    || $cust_payby->payby,
      'payinfo'  => $options{payinfo}  || $cust_payby->payinfo,
 +    'paymask'  => ( $options{payinfo}
 +                      ? FS::payinfo_Mixin->mask_payinfo( $options{payby},
 +                                                         $options{payinfo} )
 +                      : $cust_payby->paymask
 +                  ),
      'exp'      => $options{paydate}  || $cust_payby->paydate,
      'payname'  => $options{payname}  || $cust_payby->payname,
      'paytype'  => $options{paytype}  || $cust_payby->paytype,
      'amount'   => $amount,                         # consolidating
-     'paycode'  => $options{paycode}  || $cust_payby->paycode,
+     'paycode'  => $options{paycode}  || '',
    } );
    
    $cust_pay_batch->paybatchnum($old_cust_pay_batch->paybatchnum)
diff --combined FS/FS/svc_IP_Mixin.pm
@@@ -3,7 -3,8 +3,8 @@@ use base 'FS::IP_Mixin'
  
  use strict;
  use NEXT;
- use FS::Record qw(qsearchs qsearch);
+ use Carp qw(croak carp);
+ use FS::Record qw(qsearchs qsearch dbh);
  use FS::Conf;
  use FS::router;
  use FS::part_svc_router;
@@@ -80,7 -81,7 +81,7 @@@ sub svc_ip_check 
    my $error = $self->ip_check;
    return $error if $error;
    if ( my $router = $self->router ) {
 -    if ( grep { $_->routernum eq $router->routernum } $self->allowed_routers ) {
 +    if ( grep { $_->routernum == $router->routernum } $self->allowed_routers ) {
        return '';
      } else {
        return 'Router '.$router->routername.' not available for this service';
  }
  
  sub _used_addresses {
-   my ($class, $block, $exclude) = @_;
-   my $ip_field = $class->table_info->{'ip_field'}
-     or return ();
-   # if the service doesn't have an ip_field, then it has no IP addresses 
-   # in use, yes? 
-   my %hash = ( $ip_field => { op => '!=', value => '' } );
-   #$hash{'blocknum'} = $block->blocknum if $block;
-   $hash{'svcnum'} = { op => '!=', value => $exclude->svcnum } if ref $exclude;
-   map { my $na = $_->NetAddr; $na ? $na->addr : () }
-     qsearch({
-         table     => $class->table,
-         hashref   => \%hash,
-         extra_sql => " AND $ip_field != '0e0'",
-     });
+   my ($class, $block, $exclude_svc) = @_;
+   croak "_used_addresses() requires an FS::addr_block parameter"
+     unless ref $block && $block->isa('FS::addr_block');
+   my $ip_field = $class->table_info->{'ip_field'};
+   if ( !$ip_field ) {
+     carp "_used_addresses() skipped, no ip_field";
+     return;
+   }
+   my %qsearch = ( $ip_field => { op => '!=', value => '' });
+   $qsearch{svcnum} = { op => '!=', value => $exclude_svc->svcnum }
+     if ref $exclude_svc && $exclude_svc->svcnum;
+   my $block_na = $block->NetAddr;
+   my $octets;
+   if ($block->ip_netmask >= 24) {
+     $octets = 3;
+   } elsif ($block->ip_netmask >= 16) {
+     $octets = 2;
+   } elsif ($block->ip_netmask >= 8) {
+     $octets = 1;
+   }
+   #  e.g.
+   # SELECT ip_addr
+   # FROM svc_broadband
+   # WHERE ip_addr != ''
+   #   AND ip_addr != '0e0'
+   #   AND ip_addr LIKE '10.0.2.%';
+   #
+   # For /24, /16 and /8 this approach is fast, even when svc_broadband table
+   # contains 650,000+ ip records.  For other allocations, this approach is
+   # not speedy, but usable.
+   #
+   # Note: A use case like this would could greatly benefit from a qsearch()
+   #       parameter to bypass FS::Record objects creation and just
+   #       return hashrefs from DBI.  200,000 hashrefs are many seconds faster
+   #       than 200,000 FS::Record objects
+   my %qsearch_param = (
+       table     => $class->table,
+       select    => $ip_field,
+       hashref   => \%qsearch,
+       extra_sql => " AND $ip_field != '0e0' ",
+   );
+   if ( $octets ) {
+     my $block_str = join('.', (split(/\D/, $block_na->first))[0..$octets-1]);
+     $qsearch_param{extra_sql}
+       .= " AND $ip_field LIKE ".dbh->quote("${block_str}.%");
+   }
+   if ( $block->ip_netmask % 8 ) {
+     # Some addresses returned by qsearch may be outside the network block,
+     # so each ip address is tested to be in the block before it's returned.
+     return
+       grep { $block_na->contains( NetAddr::IP->new( $_ ) ) }
+       map { $_->$ip_field }
+       qsearch( \%qsearch );
+   }
+   return
+     map { $_->$ip_field }
+     qsearch( \%qsearch_param );
  }
  
  sub _is_used {
diff --combined FS/FS/svc_broadband.pm
@@@ -110,12 -110,12 +110,12 @@@ sub table_info 
        'speed_down'  => 'Download speed (Kbps)',
        'speed_up'    => 'Upload speed (Kbps)',
        'ip_addr'     => 'IP address',
 -      'blocknum'    => 
 -      { 'label' => 'Address block',
 -                         'type'  => 'select',
 -                         'select_table' => 'addr_block',
 -                          'select_key'   => 'blocknum',
 -                         'select_label' => 'cidr',
 +      'blocknum'    => {
 +                         'label'             => 'Address block',
 +                         'type'              => 'select',
 +                         'select_table'      => 'addr_block',
 +                          'select_key'       => 'blocknum',
 +                         'select_label'      => 'cidr',
                           'disable_inventory' => 1,
                         },
       'plan_id' => 'Service Plan Id',
                           #select_table => 'radius_group',
                           #select_key   => 'groupnum',
                           #select_label => 'groupname',
+                          disable_select => 1,
                           disable_inventory => 1,
                           multiple => 1,
                         },
@@@ -501,6 -502,11 +502,11 @@@ sub _upgrade_data 
      #next SVC;
    }
  
+   require FS::Misc::FixIPFormat;
+   FS::Misc::FixIPFormat::fix_bad_addresses_in_table(
+       'svc_broadband', 'svcnum', 'ip_addr',
+   );
    '';
  }
  
@@@ -523,4 -529,3 +529,3 @@@ FS::part_svc, schema.html from the bas
  =cut
  
  1;