RT# 71419 Updated Advanced wireless broadband report with new option to display packa...
[freeside.git] / FS / FS / router.pm
index 99373e5..45d9f2b 100755 (executable)
@@ -40,8 +40,9 @@ fields are currently supported:
 
 =item svcnum - svcnum of the owning FS::svc_broadband, if appropriate
 
 
 =item svcnum - svcnum of the owning FS::svc_broadband, if appropriate
 
-=item auto_addr - flag to automatically assign IP addresses to services
-linked to this router ('Y' or null).
+=item manual_addr - set to 'Y' to allow services linked to this router 
+to have any IP address, rather than one in an address block belonging 
+to the router.
 
 =back
 
 
 =back
 
@@ -62,16 +63,87 @@ sub table { 'router'; }
 Adds this record to the database.  If there is an error, returns the error,
 otherwise returns false.
 
 Adds this record to the database.  If there is an error, returns the error,
 otherwise returns false.
 
-=item delete
+If the pseudo-field 'blocknum' is set to an L<FS::addr_block> number, then 
+that address block will be assigned to this router.  Currently only one
+block can be assigned this way.
+
+=cut
 
 
-Deletes this record from the database.  If there is an error, returns the
-error, otherwise returns false.
+sub insert {
+  my $oldAutoCommit = $FS::UID::AutoCommit;
+  local $FS::UID::AutoCommit = 0;
+  my $dbh = dbh;
+
+  my $self = shift;
+  my $error = $self->SUPER::insert(@_);
+  return $error if $error;
+  if ( $self->blocknum ) {
+    my $block = FS::addr_block->by_key($self->blocknum);
+    if ($block) {
+      if ($block->routernum) {
+        $error = "block ".$block->cidr." is already assigned to a router";
+      } else {
+        $block->set('routernum', $self->routernum);
+        $block->set('manual_flag', 'Y');
+        $error = $block->replace;
+      }
+    } else {
+      $error = "blocknum ".$self->blocknum." not found";
+    }
+    if ( $error ) {
+      $dbh->rollback if $oldAutoCommit;
+      return $error;
+    }
+  }
+  $dbh->commit if $oldAutoCommit;
+  return $error;
+}
 
 =item replace OLD_RECORD
 
 Replaces OLD_RECORD with this one in the database.  If there is an error,
 returns the error, otherwise returns false.
 
 
 =item replace OLD_RECORD
 
 Replaces OLD_RECORD with this one in the database.  If there is an error,
 returns the error, otherwise returns false.
 
+=cut
+
+sub replace {
+  my $oldAutoCommit = $FS::UID::AutoCommit;
+  local $FS::UID::AutoCommit = 0;
+  my $dbh = dbh;
+
+  my $self = shift;
+  my $old = shift || $self->replace_old;
+  my $error = $self->SUPER::replace($old, @_);
+  return $error if $error;
+
+  if ( length($self->blocknum) ) {
+    #warn "FS::router::replace: blocknum = ".$self->blocknum."\n";
+    # then release any blocks we're already holding
+    foreach my $block ($self->addr_block) {
+      $block->set('routernum', 0);
+      $block->set('manual_flag', '');
+      $error ||= $block->replace;
+    }
+    if ( !$error and $self->blocknum > 0 ) {
+      # and, if the new blocknum is a real blocknum, assign it
+      my $block = FS::addr_block->by_key($self->blocknum);
+      if ( $block ) {
+        $block->set('routernum', $self->routernum);
+        $block->set('manual_flag', '');
+        $error ||= $block->replace;
+      } else {
+        $error = "blocknum ".$self->blocknum." not found";
+      }
+    }
+    if ( $error ) {
+      $dbh->rollback if $oldAutoCommit;
+      return $error;
+    }
+  }
+  $dbh->commit if $oldAutoCommit;
+  return $error;
+}
+
 =item check
 
 Checks all fields to make sure this is a valid record.  If there is an error,
 =item check
 
 Checks all fields to make sure this is a valid record.  If there is an error,
@@ -86,8 +158,9 @@ sub check {
   my $error =
     $self->ut_numbern('routernum')
     || $self->ut_text('routername')
   my $error =
     $self->ut_numbern('routernum')
     || $self->ut_text('routername')
-    || $self->ut_enum('auto_addr', [ '', 'Y' ])
+    || $self->ut_enum('manual_addr', [ '', 'Y' ])
     || $self->ut_agentnum_acl('agentnum', 'Broadband global configuration')
     || $self->ut_agentnum_acl('agentnum', 'Broadband global configuration')
+    || $self->ut_foreign_keyn('svcnum', 'cust_svc', 'svcnum')
   ;
   return $error if $error;
 
   ;
   return $error if $error;
 
@@ -96,28 +169,25 @@ sub check {
 
 =item delete
 
 
 =item delete
 
-Deletes this router if and only if no address blocks (see L<FS::addr_block>)
-are currently allocated to it.
+Deallocate all address blocks from this router and delete it.
 
 =cut
 
 sub delete {
     my $self = shift;
 
 
 =cut
 
 sub delete {
     my $self = shift;
 
-    return 'Router has address blocks allocated to it' if $self->addr_block;
-    
-    local $SIG{HUP} = 'IGNORE';
-    local $SIG{INT} = 'IGNORE';
-    local $SIG{QUIT} = 'IGNORE';
-    local $SIG{TERM} = 'IGNORE';
-    local $SIG{TSTP} = 'IGNORE';
-    local $SIG{PIPE} = 'IGNORE';
-
     my $oldAutoCommit = $FS::UID::AutoCommit;
     local $FS::UID::AutoCommit = 0;
     my $dbh = dbh;
     my $oldAutoCommit = $FS::UID::AutoCommit;
     local $FS::UID::AutoCommit = 0;
     my $dbh = dbh;
-    
-    my $error = $self->SUPER::delete;
+    my $error;
+    foreach my $block ($self->addr_block) {
+      $block->set('manual_flag', '');
+      $block->set('routernum', 0);
+      $error ||= $block->replace;
+    }
+
+    $error ||= $self->SUPER::delete;
     if ( $error ) {
        $dbh->rollback if $oldAutoCommit;
        return $error;
     if ( $error ) {
        $dbh->rollback if $oldAutoCommit;
        return $error;
@@ -132,6 +202,13 @@ sub delete {
 Returns a list of FS::addr_block objects (address blocks) associated
 with this object.
 
 Returns a list of FS::addr_block objects (address blocks) associated
 with this object.
 
+=cut
+
+sub addr_block {
+  my $self = shift;
+  qsearch('addr_block', { routernum => $self->routernum });
+}
+
 =item auto_addr_block
 
 Returns a list of address blocks on which auto-assignment of IP addresses
 =item auto_addr_block
 
 Returns a list of address blocks on which auto-assignment of IP addresses
@@ -139,14 +216,9 @@ is enabled.
 
 =cut
 
 
 =cut
 
-sub addr_block {
-  my $self = shift;
-  return qsearch('addr_block', { routernum => $self->routernum });
-}
-
 sub auto_addr_block {
   my $self = shift;
 sub auto_addr_block {
   my $self = shift;
-  return () if !$self->auto_addr;
+  return () if $self->manual_addr;
   return qsearch('addr_block', { routernum => $self->routernum,
                                  manual_flag => '' });
 }
   return qsearch('addr_block', { routernum => $self->routernum,
                                  manual_flag => '' });
 }
@@ -186,6 +258,19 @@ sub agent {
   qsearchs('agent', { 'agentnum' => shift->agentnum });
 }
 
   qsearchs('agent', { 'agentnum' => shift->agentnum });
 }
 
+=item cust_svc
+
+Returns the cust_svc associated with this router, if any.  This should be
+the service that I<provides connectivity to the router>, not any service 
+connected I<through> the router.
+
+=cut
+
+sub cust_svc {
+  my $svcnum = shift->svcnum or return undef;
+  FS::cust_svc->by_key($svcnum);
+}
+
 =back
 
 =head1 SEE ALSO
 =back
 
 =head1 SEE ALSO