allow towers without sectors, #16398 continued
authormark <mark>
Fri, 10 Feb 2012 01:58:08 +0000 (01:58 +0000)
committermark <mark>
Fri, 10 Feb 2012 01:58:08 +0000 (01:58 +0000)
FS/FS/Record.pm
FS/FS/Upgrade.pm
FS/FS/tower.pm
FS/FS/tower_sector.pm
httemplate/browse/tower.html
httemplate/edit/tower.html
httemplate/elements/select-tower_sector.html

index e4bc6c5..dfc2abf 100644 (file)
@@ -900,10 +900,12 @@ sub insert {
   my $error = $self->check;
   return $error if $error;
 
-  #single-field unique keys are given a value if false
+  #single-field non-null unique keys are given a value if empty
   #(like MySQL's AUTO_INCREMENT or Pg SERIAL)
   foreach ( $self->dbdef_table->unique_singles) {
-    $self->unique($_) unless $self->getfield($_);
+    next if $self->getfield($_);
+    next if $self->dbdef_table->column($_)->null eq 'NULL';
+    $self->unique($_);
   }
 
   #and also the primary key, if the database isn't going to
index cf61580..d00bb5c 100644 (file)
@@ -263,6 +263,8 @@ sub upgrade_data {
     'part_svc'         => [],
     'part_export'      => [],
 
+    #insert default tower_sector if not present
+    'tower',
   ;
 
   \%hash;
index 0d94477..227e3eb 100644 (file)
@@ -2,8 +2,9 @@ package FS::tower;
 
 use strict;
 use base qw( FS::o2m_Common FS::Record );
-use FS::Record qw( qsearch ); #qsearchs );
+use FS::Record qw( qsearch qsearchs );
 use FS::tower_sector;
+use List::Util qw( max );
 
 =head1 NAME
 
@@ -69,16 +70,12 @@ otherwise returns false.
 
 =cut
 
-# the insert method can be inherited from FS::Record
-
 =item delete
 
 Delete this record from the database.
 
 =cut
 
-# the delete method can be inherited from FS::Record
-
 =item replace OLD_RECORD
 
 Replaces the OLD_RECORD with this one in the database.  If there is an error,
@@ -112,10 +109,22 @@ sub check {
   $self->SUPER::check;
 }
 
+=item default_sector
+
+Returns the default sector.
+
+=cut
+
+sub default_sector {
+  my $self = shift;
+  qsearchs('tower_sector', { towernum => $self->towernum,
+                             sectorname => '_default' });
+}
+
 =item tower_sector
 
 Returns the sectors of this tower, as FS::tower_sector objects (see
-L<FS::tower_sector>).
+L<FS::tower_sector>), except for the default sector.
 
 =cut
 
@@ -123,11 +132,56 @@ sub tower_sector {
   my $self = shift;
   qsearch({
     'table'    => 'tower_sector',
-    'hashref'  => { 'towernum' => $self->towernum },
+    'hashref'  => { 'towernum'    => $self->towernum,
+                    'sectorname'  => { op => '!=', value => '_default' },
+                  },
     'order_by' => 'ORDER BY sectorname',
   });
 }
 
+=item process_o2m
+
+Wrapper for the default method (see L<FS::o2m_Common>) to manage the 
+default sector.
+
+=cut
+
+sub process_o2m {
+  my $self = shift;
+  my %opt = @_;
+  my $params = $opt{params};
+
+  # Adjust to make sure our default sector is in the list.
+  my $default_sector = $self->default_sector
+    or warn "creating default sector for tower ".$self->towernum."\n";
+  my $idx = max(0, map { $_ =~ /^sectornum(\d+)$/ ? $1 : 0 } keys(%$params));
+  $idx++; # append to the param list
+  my $prefix = "sectornum$idx";
+  # empty sectornum will create the default sector if it doesn't exist yet
+  $params->{$prefix} = $default_sector ? $default_sector->sectornum : '';
+  $params->{$prefix.'_sectorname'} = '_default';
+  $params->{$prefix.'_ip_addr'} = $params->{'default_ip_addr'} || '';
+
+  $self->SUPER::process_o2m(%opt);
+}
+
+sub _upgrade_data {
+  # Create default sectors for any tower that doesn't have one.
+  # Shouldn't do any harm if they're missing, but just for completeness.
+  my $class = shift;
+  foreach my $tower (qsearch('tower',{})) {
+    next if $tower->default_sector;
+    my $sector = FS::tower_sector->new({
+        towernum => $tower->towernum,
+        sectorname => '_default',
+        ip_addr => '',
+    });
+    my $error = $sector->insert;
+    die "error creating default sector: $error\n" if $error;
+  }
+  '';
+}
+
 =back
 
 =head1 BUGS
index 583b933..80e7f51 100644 (file)
@@ -137,7 +137,12 @@ Returns a description for this sector including tower name.
 
 sub description {
   my $self = shift;
-  $self->tower->towername. ' sector '. $self->sectorname;
+  if ( $self->sectorname eq '_default' ) {
+    $self->tower->towername
+  }
+  else {
+    $self->tower->towername. ' sector '. $self->sectorname
+  }
 }
 
 =back
index 82eb872..7767a3c 100644 (file)
@@ -51,7 +51,9 @@ my $num_svc_links = sub {
 
 my $tower_sub = sub {
   my $tower = shift;
-  my $sectors = join(',', map { $_->sectornum } $tower->tower_sector);
+  my $sectors = join(',', 
+    map { $_->sectornum } $tower->tower_sector, $tower->default_sector
+  );
   [ #rows
     [
       { 'data' => $tower->towername, },
index c27d9d2..5a0f2a8 100644 (file)
@@ -4,6 +4,8 @@
      viewall_dir   => 'browse',
      fields        => [ 'towername',
                         { field=>'disabled', type=>'checkbox', value=>'Y', },
+                        { field             => 'default_ip_addr',
+                          curr_value_callback => $default_ip_addr_callback },
                         { field             => 'sectornum',
                           type              => 'tower_sector',
                           o2m_table         => 'tower_sector',
@@ -15,6 +17,7 @@
                         'towername' => 'Name',
                         'sectornum' => 'Sector',
                         'disabled'  => 'Disabled',
+                        'default_ip_addr' => 'Tower IP address',
                       },
 &>
 <%init>
@@ -34,4 +37,10 @@ my $m2_error_callback = sub { # reconstruct the list
   } grep /^sectornum\d+$/, ($cgi->param);
 };
 
+my $default_ip_addr_callback = sub {
+  my ($cgi, $object) = @_;
+  my $sector = $object ? $object->default_sector : '';
+  $sector ? $sector->ip_addr : '';
+};
+
 </%init>
index c783c4b..a16d3bf 100644 (file)
@@ -40,12 +40,28 @@ change_towernum('');
 my %opt = @_;
 
 my %sectors_of;
+my %default_of;
 if ( $opt{'multiple'} ) {
   foreach my $sector ( qsearch('tower_sector',{}) ) {
     $sectors_of{$sector->towernum} ||= {};
     $sectors_of{$sector->towernum}->{$sector->sectornum} = $sector->sectorname;
     $sectors_of{''}->{$sector->sectornum} = $sector->description;
+    $default_of{$sector->towernum} = $sector->sectornum
+      if $sector->sectorname eq '_default';
   }
 }
+foreach my $towernum (keys %sectors_of) {
+  # hide default sectors for towers that have real sectors defined
+  my $sectornum = $default_of{$towernum};
+  if ( keys %{ $sectors_of{$towernum} } > 1 ) {
+    delete $sectors_of{$towernum}->{$sectornum};
+    delete $sectors_of{''}->{$sectornum};
+  }
+  else {
+  # show default sectorname as '(all)'
+    $sectors_of{$towernum}->{$sectornum} = '(all)'
+  }
+}
+
 my $empty_label = $opt{'empty_label'} || 'Include services with no tower/sector';
 </%init>