1 package FS::deploy_zone;
4 use base qw( FS::o2m_Common FS::Record );
5 use FS::Record qw( qsearch qsearchs dbh );
11 FS::deploy_zone - Object methods for deploy_zone records
17 $record = new FS::deploy_zone \%hash;
18 $record = new FS::deploy_zone { 'column' => 'value' };
20 $error = $record->insert;
22 $error = $new_record->replace($old_record);
24 $error = $record->delete;
26 $error = $record->check;
30 An FS::deploy_zone object represents a geographic zone where a certain kind
31 of service is available. Currently we store this information to generate
32 the FCC Form 477 deployment reports, but it may find other uses later.
34 FS::deploy_zone inherits from FS::Record. The following fields are currently
45 Optional text describing the zone.
49 The agent that serves this zone.
53 The name under which service is marketed in this zone. If null, will
54 default to the agent name.
58 The way the zone geography is defined: "B" for a list of census blocks
59 (used by the FCC for fixed broadband service), "P" for a polygon (for
60 mobile services). See L<FS::deploy_zone_block> and L<FS::deploy_zone_vertex>.
64 The FCC technology code for the type of service available.
68 For mobile service zones, the FCC code for the RF band.
72 For broadband, the advertised upstream bandwidth in the zone. If multiple
73 speed tiers are advertised, use the highest.
77 For broadband, the advertised downstream bandwidth in the zone.
81 For broadband, the contractually guaranteed upstream bandwidth, if that type
86 For broadband, the contractually guaranteed downstream bandwidth, if that
87 type of service is sold.
91 'Y' if this service is sold for consumer/household use.
95 'Y' if this service is sold to business or institutional use. Not mutually
96 exclusive with is_consumer.
100 'Y' if this service includes broadband Internet.
104 'Y' if this service includes voice communication.
108 The date this zone became active.
112 The date this zone became inactive, if any.
122 Creates a new zone. To add the zone to the database, see L<"insert">.
126 # the new method can be inherited from FS::Record, if a table method is defined
128 sub table { 'deploy_zone'; }
130 =item insert ELEMENTS
132 Adds this record to the database. If there is an error, returns the error,
133 otherwise returns false.
137 # the insert method can be inherited from FS::Record
141 Delete this record from the database.
146 my $oldAutoCommit = $FS::UID::AutoCommit;
147 local $FS::UID::AutoCommit = 0;
148 # clean up linked records
150 my $error = $self->process_o2m(
151 'table' => $self->element_table,
152 'num_col' => 'zonenum',
153 'fields' => 'zonenum',
155 ) || $self->SUPER::delete(@_);
158 dbh->rollback if $oldAutoCommit;
164 =item replace OLD_RECORD
166 Replaces the OLD_RECORD with this one in the database. If there is an error,
167 returns the error, otherwise returns false.
171 # the replace method can be inherited from FS::Record
175 Checks all fields to make sure this is a valid zone record. If there is
176 an error, returns the error, otherwise returns false. Called by the insert
185 $self->ut_numbern('zonenum')
186 || $self->ut_text('description')
187 || $self->ut_number('agentnum')
188 || $self->ut_foreign_key('agentnum', 'agent', 'agentnum')
189 || $self->ut_textn('dbaname')
190 || $self->ut_enum('zonetype', [ 'B', 'P' ])
191 || $self->ut_number('technology')
192 || $self->ut_numbern('spectrum')
193 || $self->ut_decimaln('adv_speed_up', 3)
194 || $self->ut_decimaln('adv_speed_down', 3)
195 || $self->ut_decimaln('cir_speed_up', 3)
196 || $self->ut_decimaln('cir_speed_down', 3)
197 || $self->ut_flag('is_consumer')
198 || $self->ut_flag('is_business')
199 || $self->ut_flag('is_broadband')
200 || $self->ut_flag('is_voice')
201 || $self->ut_numbern('active_date')
202 || $self->ut_numbern('expire_date')
204 return $error if $error;
206 foreach(qw(adv_speed_down adv_speed_up cir_speed_down cir_speed_up)) {
207 if ($self->get('is_broadband')) {
208 if (!$self->get($_)) {
215 if (!$self->get('active_date')) {
216 $self->set('active_date', time);
224 Returns the name of the table that contains the zone's elements (blocks or
231 if ($self->zonetype eq 'B') {
232 return 'deploy_zone_block';
233 } elsif ( $self->zonetype eq 'P') {
234 return 'deploy_zone_vertex';
236 die 'unknown zonetype';
240 =item deploy_zone_block
242 Returns the census block records in this zone, in order by census block
243 number. Only appropriate to block-type zones.
245 =item deploy_zone_vertex
247 Returns the vertex records for this zone, in order by sequence number. Only
248 appropriate to polygon-type zones.
252 sub deploy_zone_block {
255 table => 'deploy_zone_block',
256 hashref => { zonenum => $self->zonenum },
257 order_by => ' ORDER BY censusblock',
261 sub deploy_zone_vertex {
264 table => 'deploy_zone_vertex',
265 hashref => { zonenum => $self->zonenum },
266 order_by => ' ORDER BY vertexnum',
276 =item process_batch_import JOB, PARAMS
280 sub process_batch_import {
282 use FS::deploy_zone_block;
283 use FS::deploy_zone_vertex;
288 $param = thaw(decode_base64($param));
291 # even if creating a new zone, the deploy_zone object should already
292 # be inserted by this point
293 my $zonenum = $param->{zonenum}
294 or die "zonenum required";
295 my $zone = FS::deploy_zone->by_key($zonenum)
296 or die "deploy_zone #$zonenum not found";
298 if ( $zone->zonetype eq 'B' ) {
299 $opt = { 'table' => 'deploy_zone_block',
300 'params' => [ 'zonenum', 'censusyear' ],
301 'formats' => { 'plain' => [ 'censusblock' ] },
304 $job->update_statustext('1,Inserting census blocks');
305 } elsif ( $zone->zonetype eq 'P' ) {
306 $opt = { 'table' => 'deploy_zone_vertex',
307 'params' => [ 'zonenum' ],
308 'formats' => { 'plain' => [ 'latitude', 'longitude' ] },
312 die "don't know how to import to zonetype ".$zone->zonetype;
315 FS::Record::process_batch_import( $job, $opt, $param );