'description' => 'Descriptive label for this particular device',
'speed_down' => 'Maximum download speed for this service in Kbps. 0 denotes unlimited.',
'speed_up' => 'Maximum upload speed for this service in Kbps. 0 denotes unlimited.',
- #'ip_addr' => 'IP address. Leave blank for automatic assignment.',
- #'blocknum' =>
- #{ 'label' => 'Address block',
- # 'type' => 'select',
- # 'select_table' => 'addr_block',
- # 'select_key' => 'blocknum',
- # 'select_label' => 'cidr',
- # 'disable_inventory' => 1,
- # },
+ 'ip_addr' => 'IP address. Leave blank for automatic assignment.',
+ 'blocknum' =>
+ { 'label' => 'Address block',
+ 'type' => 'select',
+ 'select_table' => 'addr_block',
+ 'select_key' => 'blocknum',
+ 'select_label' => 'cidr',
+ 'disable_inventory' => 1,
+ },
'plan_id' => 'Service Plan Id',
'performance_profile' => 'Peformance Profile',
'authkey' => 'Authentication key',
sub table { 'svc_broadband'; }
-sub table_dupcheck_fields { ( 'mac_addr' ); }
+sub table_dupcheck_fields { ( 'ip_addr', 'mac_addr' ); }
=item search HASHREF
}
my $agentnum = $cust_pkg->cust_main->agentnum if $cust_pkg;
- if ($self->routernum) {
+ if ( $conf->exists('auto_router') and $self->ip_addr and !$self->routernum ) {
+ # assign_router is guaranteed to provide a router that's legal
+ # for this agent and svcpart
+ my $error = $self->_check_ip_addr || $self->assign_router;
+ return $error if $error;
+ }
+ elsif ($self->routernum) {
return "Router ".$self->routernum." does not provide this service"
unless qsearchs('part_svc_router', {
svcpart => $svcpart,
my $router = $self->router;
return "Router ".$self->routernum." does not serve this customer"
- if $router->agentnum and $router->agentnum != $agentnum;
+ if $router->agentnum and $agentnum and $router->agentnum != $agentnum;
- if ( $router->auto_addr ) {
- my $error = $self->assign_ip_addr;
- return $error if $error;
+ if ( $router->manual_addr ) {
+ $self->blocknum('');
}
else {
- $self->blocknum('');
+ my $addr_block = $self->addr_block;
+ unless ( $addr_block and $addr_block->manual_flag ) {
+ my $error = $self->assign_ip_addr;
+ return $error if $error;
+ }
}
+
+ my $error = $self->_check_ip_addr;
+ return $error if $error;
} # if $self->routernum
if ( $cust_pkg && ! $self->latitude && ! $self->longitude ) {
}
}
- $error = $self->_check_ip_addr;
- return $error if $error;
-
$self->SUPER::check;
}
=item assign_ip_addr
-Assign an address block matching the selected router, and the selected block
+Assign an IP address matching the selected router, and the selected block
if there is one.
=cut
else {
return '';
}
+#warn "assigning ip address in blocks\n".join("\n",map{$_->cidr} @blocks)."\n";
foreach my $block ( @blocks ) {
if ( $self->ip_addr and $block->NetAddr->contains($self->NetAddr) ) {
}
}
+=item assign_router
+
+Assign an address block and router matching the selected IP address.
+Does nothing if IP address is null.
+
+=cut
+
+sub assign_router {
+ my $self = shift;
+ return '' if !$self->ip_addr;
+ #warn "assigning router/block for ".$self->ip_addr."\n";
+ foreach my $router ($self->allowed_routers) {
+ foreach my $block ($router->addr_block) {
+ if ( $block->NetAddr->contains($self->NetAddr) ) {
+ $self->blocknum($block->blocknum);
+ $self->routernum($block->routernum);
+ return '';
+ }
+ }
+ }
+ return $self->ip_addr.' is not in an allowed block.';
+}
+
sub _check_ip_addr {
my $self = shift;
return '' if $conf->exists('svc_broadband-allow_null_ip_addr');
return 'IP address required';
}
+ else {
+ return 'Cannot parse address: '.$self->ip_addr unless $self->NetAddr;
+ }
# if (my $dup = qsearchs('svc_broadband', {
# ip_addr => $self->ip_addr,
# svcnum => {op=>'!=', value => $self->svcnum}
sub _check_duplicate {
my $self = shift;
- return "MAC already in use"
- if ( $self->mac_addr &&
- scalar( qsearch( 'svc_broadband', { 'mac_addr', $self->mac_addr } ) )
- );
+ $self->lock_table;
+
+ my @dup;
+ @dup = $self->find_duplicates('global', 'ip_addr');
+ if ( @dup ) {
+ return "IP address in use (svcnum ".$dup[0]->svcnum.")";
+ }
+ @dup = $self->find_duplicates('global', 'mac_addr');
+ if ( @dup ) {
+ return "MAC address in use (svcnum ".$dup[0]->svcnum.")";
+ }
'';
}
sub allowed_routers {
my $self = shift;
my $svcpart = $self->svcnum ? $self->cust_svc->svcpart : $self->svcpart;
- map { $_->router } qsearch('part_svc_router',
- { svcpart => $self->cust_svc->svcpart });
+ my @r = map { $_->router } qsearch('part_svc_router',
+ { svcpart => $svcpart });
+ if ( $self->cust_main ) {
+ my $agentnum = $self->cust_main->agentnum;
+ return grep { !$_->agentnum or $_->agentnum == $agentnum } @r;
+ }
+ else {
+ return @r;
+ }
}
=back
join( $delim || '', $addr =~ /../g );
}
-=back
-
-
#class method
sub _upgrade_data {
my $class = shift;
+ local($FS::svc_Common::noexport_hack) = 1;
+
# set routernum to addr_block.routernum
foreach my $self (qsearch('svc_broadband', {
blocknum => {op => '!=', value => ''},
routernum => ''
})) {
my $addr_block = $self->addr_block;
- if ( my $routernum = $addr_block->routernum ) {
+ my $ip_addr = $self->ip_addr;
+ my $routernum = $addr_block->routernum;
+ if ( $routernum ) {
$self->set(routernum => $routernum);
- my $error = $self->replace;
- die "error assigning routernum $routernum to service ".$self->svcnum.
- ":\n$error\n"
+ my $error = $self->check;
+ # sanity check: don't allow this to change IP address or block
+ # (other than setting blocknum to null for a non-auto-assigned router)
+ if ( $self->ip_addr ne $ip_addr
+ or ($self->blocknum and $self->blocknum != $addr_block->blocknum)) {
+ warn "WARNING: Upgrading service ".$self->svcnum." would change its block/address; skipped.\n";
+ next;
+ }
+
+ $error ||= $self->replace;
+ warn "WARNING: error assigning routernum $routernum to service ".$self->svcnum.
+ ":\n$error; skipped\n"
if $error;
}
else {
'';
}
+=back
+
=head1 BUGS
The business with sb_field has been 'fixed', in a manner of speaking.