change calculation method for prepaid income report, #13289
[freeside.git] / FS / FS / addr_block.pm
index 0fe2476..e00f587 100755 (executable)
@@ -8,6 +8,7 @@ use FS::svc_broadband;
 use FS::Conf;
 use NetAddr::IP;
 use Carp qw( carp );
 use FS::Conf;
 use NetAddr::IP;
 use Carp qw( carp );
+use List::Util qw( first );
 
 @ISA = qw( FS::Record );
 
 
 @ISA = qw( FS::Record );
 
@@ -76,14 +77,35 @@ otherwise returns false.
 Deletes this record from the database.  If there is an error, returns the
 error, otherwise returns false.
 
 Deletes this record from the database.  If there is an error, returns the
 error, otherwise returns false.
 
+=cut
+
 sub delete {
   my $self = shift;
 sub delete {
   my $self = shift;
-  return 'Block must be deallocated before deletion'
-    if $self->router;
-
-  $self->SUPER::delete;
+  return 'Block must be deallocated and have no services before deletion'
+    if $self->router || $self->svc_broadband;
+
+    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 $error = $self->SUPER::delete;
+    if ( $error ) {
+       $dbh->rollback if $oldAutoCommit;
+       return $error;
+    }
+  
+    $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+    '';
 }
 
 }
 
+
 =item replace OLD_RECORD
 
 Replaces OLD_RECORD with this one in the database.  If there is an error,
 =item replace OLD_RECORD
 
 Replaces OLD_RECORD with this one in the database.  If there is an error,
@@ -201,39 +223,45 @@ sub cidr {
   $self->NetAddr->cidr;
 }
 
   $self->NetAddr->cidr;
 }
 
-=item next_free_addr
+=item free_addrs
 
 Returns a NetAddr::IP object corresponding to the first unassigned address 
 in the block (other than the network, broadcast, or gateway address).  If 
 
 Returns a NetAddr::IP object corresponding to the first unassigned address 
 in the block (other than the network, broadcast, or gateway address).  If 
-there are no free addresses, returns false.  There are never free addresses
+there are no free addresses, returns nothing.  There are never free addresses
 when manual_flag is true.
 
 when manual_flag is true.
 
+=item next_free_addr
+
+Returns a NetAddr::IP object for the first unassigned address in the block,
+or '' if there are none.
+
 =cut
 
 =cut
 
-sub next_free_addr {
+sub free_addrs {
   my $self = shift;
 
   my $self = shift;
 
-  return '' if $self->manual_flag;
+  return if $self->manual_flag;
 
   my $conf = new FS::Conf;
   my @excludeaddr = $conf->config('exclude_ip_addr');
   
 
   my $conf = new FS::Conf;
   my @excludeaddr = $conf->config('exclude_ip_addr');
   
-my @used =
-( (map { $_->NetAddr->addr }
-    ($self,
-     qsearch('svc_broadband', { blocknum => $self->blocknum }))
-  ), @excludeaddr
-);
-
-  my @free = $self->NetAddr->hostenum;
-  while (my $ip = shift @free) {
-    if (not grep {$_ eq $ip->addr;} @used) { return $ip; };
-  }
+  my %used = map { $_ => 1 }
+  (
+    (map { $_->NetAddr->addr }
+      ($self,
+       qsearch('svc_broadband', { blocknum => $self->blocknum }))
+    ), @excludeaddr
+  );
 
 
-  '';
+  grep { !$used{$_->addr} } $self->NetAddr->hostenum;
 
 }
 
 
 }
 
+sub next_free_addr {
+  my $self = shift;
+  ($self->free_addrs, '')[0]
+}
+
 =item allocate -- deprecated
 
 Allocates this address block to a router.  Takes an FS::router object 
 =item allocate -- deprecated
 
 Allocates this address block to a router.  Takes an FS::router object