backup the schema for tables we don't need the data from. RT#85959
[freeside.git] / FS / FS / tower.pm
1 package FS::tower;
2 use base qw( FS::o2m_Common FS::Record );
3
4 use strict;
5 use List::Util qw( max );
6 use FS::Record qw( qsearch qsearchs );
7 use FS::tower_sector;
8
9 =head1 NAME
10
11 FS::tower - Object methods for tower records
12
13 =head1 SYNOPSIS
14
15   use FS::tower;
16
17   $record = new FS::tower \%hash;
18   $record = new FS::tower { 'column' => 'value' };
19
20   $error = $record->insert;
21
22   $error = $new_record->replace($old_record);
23
24   $error = $record->delete;
25
26   $error = $record->check;
27
28 =head1 DESCRIPTION
29
30 An FS::tower object represents a tower.  FS::tower inherits from
31 FS::Record.  The following fields are currently supported:
32
33 =over 4
34
35 =item towernum
36
37 primary key
38
39 =item towername
40
41 Tower name
42
43 =item disabled
44
45 Disabled flag, empty or 'Y'
46
47 =item up_rate_limit
48
49 Up Rate limit for towner
50
51 =item down_rate_limit
52
53 Down Rate limit for tower
54
55 =back
56
57 =head1 METHODS
58
59 =over 4
60
61 =item new HASHREF
62
63 Creates a new tower.  To add the tower to the database, see L<"insert">.
64
65 Note that this stores the hash reference, not a distinct copy of the hash it
66 points to.  You can ask the object for a copy with the I<hash> method.
67
68 =cut
69
70 sub table { 'tower'; }
71
72 =item insert
73
74 Adds this record to the database.  If there is an error, returns the error,
75 otherwise returns false.
76
77 =item delete
78
79 Delete this record from the database.
80
81 =item replace OLD_RECORD
82
83 Replaces the OLD_RECORD with this one in the database.  If there is an error,
84 returns the error, otherwise returns false.
85
86 =cut
87
88 sub replace {
89   my $self = shift;
90   my $old = shift || $self->replace_old;
91   # editing the tower location needs to regenerate coverage on its sectors
92   my $regen_coverage = 0;
93   foreach (qw(latitude longitude height)) {
94     $regen_coverage = 1 if $self->get($_) != $old->get($_);
95   }
96
97   my $error = $self->SUPER::replace($old);
98   return $error if $error;
99
100   if ($regen_coverage) {
101     foreach my $sector ($self->tower_sector) {
102       $sector->queue_generate_coverage;
103     }
104   }
105 }
106
107 =item check
108
109 Checks all fields to make sure this is a valid tower.  If there is
110 an error, returns the error, otherwise returns false.  Called by the insert
111 and replace methods.
112
113 =cut
114
115 sub check {
116   my $self = shift;
117
118   my $error = 
119     $self->ut_numbern('towernum')
120     || $self->ut_text('towername')
121     || $self->ut_enum('disabled', [ '', 'Y' ])
122     || $self->ut_coordn('latitude')
123     || $self->ut_coordn('longitude')
124     || $self->ut_enum('coord_auto', [ '', 'Y' ])
125     || $self->ut_floatn('altitude')
126     || $self->ut_floatn('height')
127     || $self->ut_floatn('veg_height')
128     || $self->ut_alphan('color')
129     || $self->ut_numbern('up_rate_limit')
130     || $self->ut_numbern('down_rate_limit')
131   ;
132   return $error if $error;
133
134   $self->SUPER::check;
135 }
136
137 =item default_sector
138
139 Returns the default sector.
140
141 =cut
142
143 sub default_sector {
144   my $self = shift;
145   qsearchs('tower_sector', { towernum => $self->towernum,
146                              sectorname => '_default' });
147 }
148
149 =item tower_sector
150
151 Returns the sectors of this tower, as FS::tower_sector objects (see
152 L<FS::tower_sector>), except for the default sector.
153
154 =cut
155
156 sub tower_sector {
157   my $self = shift;
158   qsearch({
159     'table'    => 'tower_sector',
160     'hashref'  => { 'towernum'    => $self->towernum,
161                     'sectorname'  => { op => '!=', value => '_default' },
162                   },
163     'order_by' => 'ORDER BY sectorname',
164   });
165 }
166
167 =item process_o2m
168
169 Wrapper for the default method (see L<FS::o2m_Common>) to manage the 
170 default sector.
171
172 =cut
173
174 sub process_o2m {
175   my $self = shift;
176   my %opt = @_;
177   my $params = +{ %{$opt{params}} };
178
179   # Adjust to make sure our default sector is in the list.
180   my $default_sector = $self->default_sector
181     or warn "creating default sector for tower ".$self->towernum."\n";
182   my $idx = max(0, map { $_ =~ /^sectornum(\d+)$/ ? $1 : 0 } keys(%$params));
183   $idx++; # append to the param list
184   my $prefix = "sectornum$idx";
185   # empty sectornum will create the default sector if it doesn't exist yet
186   $params->{$prefix} = $default_sector ? $default_sector->sectornum : '';
187   $params->{$prefix.'_sectorname'} = '_default';
188   $params->{$prefix.'_ip_addr'} = $params->{'default_ip_addr'} || '';
189
190   $self->SUPER::process_o2m(%opt);
191 }
192
193 sub _upgrade_data {
194   # Create default sectors for any tower that doesn't have one.
195   # Shouldn't do any harm if they're missing, but just for completeness.
196   my $class = shift;
197   foreach my $tower (qsearch('tower',{})) {
198     next if $tower->default_sector;
199     my $sector = FS::tower_sector->new({
200         towernum => $tower->towernum,
201         sectorname => '_default',
202         ip_addr => '',
203     });
204     my $error = $sector->insert;
205     die "error creating default sector: $error\n" if $error;
206   }
207   '';
208 }
209
210 =back
211
212 =head1 BUGS
213
214 =head1 SEE ALSO
215
216 L<FS::tower_sector>, L<FS::svc_broadband>, L<FS::Record>
217
218 =cut
219
220 1;
221