Merge branch 'master' of git.freeside.biz:/home/git/freeside
[freeside.git] / FS / FS / deploy_zone.pm
1 package FS::deploy_zone;
2
3 use strict;
4 use base qw( FS::o2m_Common FS::Record );
5 use FS::Record qw( qsearch qsearchs dbh );
6
7 =head1 NAME
8
9 FS::deploy_zone - Object methods for deploy_zone records
10
11 =head1 SYNOPSIS
12
13   use FS::deploy_zone;
14
15   $record = new FS::deploy_zone \%hash;
16   $record = new FS::deploy_zone { 'column' => 'value' };
17
18   $error = $record->insert;
19
20   $error = $new_record->replace($old_record);
21
22   $error = $record->delete;
23
24   $error = $record->check;
25
26 =head1 DESCRIPTION
27
28 An FS::deploy_zone object represents a geographic zone where a certain kind
29 of service is available.  Currently we store this information to generate
30 the FCC Form 477 deployment reports, but it may find other uses later.
31
32 FS::deploy_zone inherits from FS::Record.  The following fields are currently
33 supported:
34
35 =over 4
36
37 =item zonenum
38
39 primary key
40
41 =item description
42
43 Optional text describing the zone.
44
45 =item agentnum
46
47 The agent that serves this zone.
48
49 =item dbaname
50
51 The name under which service is marketed in this zone.  If null, will 
52 default to the agent name.
53
54 =item zonetype
55
56 The way the zone geography is defined: "B" for a list of census blocks
57 (used by the FCC for fixed broadband service), "P" for a polygon (for 
58 mobile services).  See L<FS::deploy_zone_block> and L<FS::deploy_zone_vertex>.
59
60 =item technology
61
62 The FCC technology code for the type of service available.
63
64 =item spectrum
65
66 For mobile service zones, the FCC code for the RF band.
67
68 =item adv_speed_up
69
70 For broadband, the advertised upstream bandwidth in the zone.  If multiple
71 speed tiers are advertised, use the highest.
72
73 =item adv_speed_down
74
75 For broadband, the advertised downstream bandwidth in the zone.
76
77 =item cir_speed_up
78
79 For broadband, the contractually guaranteed upstream bandwidth, if that type
80 of service is sold.
81
82 =item cir_speed_down
83
84 For broadband, the contractually guaranteed downstream bandwidth, if that 
85 type of service is sold.
86
87 =item is_consumer
88
89 'Y' if this service is sold for consumer/household use.
90
91 =item is_business
92
93 'Y' if this service is sold to business or institutional use.  Not mutually
94 exclusive with is_consumer.
95
96 =item is_broadband
97
98 'Y' if this service includes broadband Internet.
99
100 =item is_voice
101
102 'Y' if this service includes voice communication.
103
104 =item active_date
105
106 The date this zone became active.
107
108 =item expire_date
109
110 The date this zone became inactive, if any.
111
112 =back
113
114 =head1 METHODS
115
116 =over 4
117
118 =item new HASHREF
119
120 Creates a new zone.  To add the zone to the database, see L<"insert">.
121
122 =cut
123
124 # the new method can be inherited from FS::Record, if a table method is defined
125
126 sub table { 'deploy_zone'; }
127
128 =item insert ELEMENTS
129
130 Adds this record to the database.  If there is an error, returns the error,
131 otherwise returns false.
132
133 =cut
134
135 # the insert method can be inherited from FS::Record
136
137 =item delete
138
139 Delete this record from the database.
140
141 =cut
142
143 sub delete {
144   my $oldAutoCommit = $FS::UID::AutoCommit;
145   local $FS::UID::AutoCommit = 0;
146   # clean up linked records
147   my $self = shift;
148   my $error = $self->process_o2m(
149     'table'   => $self->element_table,
150     'num_col' => 'zonenum',
151     'fields'  => 'zonenum',
152     'params'  => {},
153   ) || $self->SUPER::delete(@_);
154   
155   if ($error) {
156     dbh->rollback if $oldAutoCommit;
157     return $error;
158   }
159   '';
160 }
161
162 =item replace OLD_RECORD
163
164 Replaces the OLD_RECORD with this one in the database.  If there is an error,
165 returns the error, otherwise returns false.
166
167 =cut
168
169 # the replace method can be inherited from FS::Record
170
171 =item check
172
173 Checks all fields to make sure this is a valid zone record.  If there is
174 an error, returns the error, otherwise returns false.  Called by the insert
175 and replace methods.
176
177 =cut
178
179 sub check {
180   my $self = shift;
181
182   my $error = 
183     $self->ut_numbern('zonenum')
184     || $self->ut_textn('description')
185     || $self->ut_number('agentnum')
186     || $self->ut_foreign_key('agentnum', 'agent', 'agentnum')
187     || $self->ut_textn('dbaname')
188     || $self->ut_enum('zonetype', [ 'B', 'P' ])
189     || $self->ut_number('technology')
190     || $self->ut_numbern('spectrum')
191     || $self->ut_decimaln('adv_speed_up', 3)
192     || $self->ut_decimaln('adv_speed_down', 3)
193     || $self->ut_decimaln('cir_speed_up', 3)
194     || $self->ut_decimaln('cir_speed_down', 3)
195     || $self->ut_flag('is_consumer')
196     || $self->ut_flag('is_business')
197     || $self->ut_flag('is_broadband')
198     || $self->ut_flag('is_voice')
199     || $self->ut_numbern('active_date')
200     || $self->ut_numbern('expire_date')
201   ;
202   return $error if $error;
203
204   foreach(qw(adv_speed_down adv_speed_up cir_speed_down cir_speed_up)) {
205     if ($self->get('is_broadband')) {
206       if (!$self->get($_)) {
207         $self->set($_, 0);
208       }
209     } else {
210       $self->set($_, '');
211     }
212   }
213   if (!$self->get('active_date')) {
214     $self->set('active_date', time);
215   }
216
217   $self->SUPER::check;
218 }
219
220 =item element_table
221
222 Returns the name of the table that contains the zone's elements (blocks or
223 vertices).
224
225 =cut
226
227 sub element_table {
228   my $self = shift;
229   if ($self->zonetype eq 'B') {
230     return 'deploy_zone_block';
231   } elsif ( $self->zonetype eq 'P') {
232     return 'deploy_zone_vertex';
233   } else {
234     die 'unknown zonetype';
235   }
236 }
237
238 =item deploy_zone_block
239
240 Returns the census block records in this zone, in order by census block
241 number.  Only appropriate to block-type zones.
242
243 =item deploy_zone_vertex
244
245 Returns the vertex records for this zone, in order by sequence number.  Only
246 appropriate to polygon-type zones.
247
248 =cut
249
250 sub deploy_zone_block {
251   my $self = shift;
252   qsearch({
253       table     => 'deploy_zone_block',
254       hashref   => { zonenum => $self->zonenum },
255       order_by  => ' ORDER BY censusblock',
256   });
257 }
258
259 sub deploy_zone_vertex {
260   my $self = shift;
261   qsearch({
262       table     => 'deploy_zone_vertex',
263       hashref   => { zonenum => $self->zonenum },
264       order_by  => ' ORDER BY vertexnum',
265   });
266 }
267
268 =head1 BUGS
269
270 =head1 SEE ALSO
271
272 L<FS::Record>
273
274 =cut
275
276 1;
277