1 package FS::svc_broadband;
4 use vars qw(@ISA $conf);
5 use FS::Record qw( qsearchs qsearch dbh );
11 @ISA = qw( FS::svc_Common );
13 $FS::UID::callback{'FS::svc_broadband'} = sub {
19 FS::svc_broadband - Object methods for svc_broadband records
23 use FS::svc_broadband;
25 $record = new FS::svc_broadband \%hash;
26 $record = new FS::svc_broadband { 'column' => 'value' };
28 $error = $record->insert;
30 $error = $new_record->replace($old_record);
32 $error = $record->delete;
34 $error = $record->check;
36 $error = $record->suspend;
38 $error = $record->unsuspend;
40 $error = $record->cancel;
44 An FS::svc_broadband object represents a 'broadband' Internet connection, such
45 as a DSL, cable modem, or fixed wireless link. These services are assumed to
46 have the following properties:
48 FS::svc_broadband inherits from FS::svc_Common. The following fields are
53 =item svcnum - primary key
55 =item blocknum - see FS::addr_block
58 speed_up - maximum upload speed, in bits per second. If set to zero, upload
59 speed will be unlimited. Exports that do traffic shaping should handle this
60 correctly, and not blindly set the upload speed to zero and kill the customer's
64 speed_down - maximum download speed, as above
66 =item ip_addr - the customer's IP address. If the customer needs more than one
67 IP address, set this to the address of the customer's router. As a result, the
68 customer's router will have the same address for both its internal and external
69 interfaces thus saving address space. This has been found to work on most NAT
80 Creates a new svc_broadband. To add the record to the database, see
83 Note that this stores the hash reference, not a distinct copy of the hash it
84 points to. You can ask the object for a copy with the I<hash> method.
88 sub table { 'svc_broadband'; }
92 Adds this record to the database. If there is an error, returns the error,
93 otherwise returns false.
95 The additional fields pkgnum and svcpart (see FS::cust_svc) should be
96 defined. An FS::cust_svc record will be created and inserted.
100 # Standard FS::svc_Common::insert
104 Delete this record from the database.
108 # Standard FS::svc_Common::delete
110 =item replace OLD_RECORD
112 Replaces the OLD_RECORD with this one in the database. If there is an error,
113 returns the error, otherwise returns false.
117 # Standard FS::svc_Common::replace
121 Returns a list of FS::sb_field objects assigned to this object.
128 return qsearch( 'sb_field', { svcnum => $self->svcnum } );
131 =item sb_field_hashref
133 Returns a hashref of the FS::sb_field key/value pairs for this object.
135 Deprecated. Please don't use it.
139 # Kristian wrote this, but don't hold it against him. He was under a powerful
140 # distracting influence whom he evidently found much more interesting than
141 # svc_broadband.pm. I can't say I blame him.
143 sub sb_field_hashref {
147 if ((not $svcpart) && ($self->cust_svc)) {
148 $svcpart = $self->cust_svc->svcpart;
154 my $sb_field = qsearchs('sb_field', { sbfieldpart => $_->sbfieldpart,
155 svcnum => $self->svcnum });
156 $hashref->{$_->getfield('name')} = $sb_field ? $sb_field->getfield('value') : '';
157 } qsearch('part_sb_field', { svcpart => $svcpart });
165 Called by the suspend method of FS::cust_pkg (see FS::cust_pkg).
169 Called by the unsuspend method of FS::cust_pkg (see FS::cust_pkg).
173 Called by the cancel method of FS::cust_pkg (see FS::cust_pkg).
177 Checks all fields to make sure this is a valid broadband service. If there is
178 an error, returns the error, otherwise returns false. Called by the insert
185 my $x = $self->setfixed;
187 return $x unless ref($x);
190 $self->ut_numbern('svcnum')
191 || $self->ut_foreign_key('blocknum', 'addr_block', 'blocknum')
192 || $self->ut_number('speed_up')
193 || $self->ut_number('speed_down')
194 || $self->ut_ipn('ip_addr')
196 return $error if $error;
198 if($self->speed_up < 0) { return 'speed_up must be positive'; }
199 if($self->speed_down < 0) { return 'speed_down must be positive'; }
201 if (not($self->ip_addr) or $self->ip_addr eq '0.0.0.0') {
202 $self->ip_addr($self->addr_block->next_free_addr->addr);
203 if (not $self->ip_addr) {
204 return "No free addresses in addr_block (blocknum: ".$self->blocknum.")";
208 # This should catch errors in the ip_addr. If it doesn't,
209 # they'll almost certainly not map into the block anyway.
210 my $self_addr = $self->NetAddr; #netmask is /32
211 return ('Cannot parse address: ' . $self->ip_addr) unless $self_addr;
213 my $block_addr = $self->addr_block->NetAddr;
214 unless ($block_addr->contains($self_addr)) {
215 return 'blocknum '.$self->blocknum.' does not contain address '.$self->ip_addr;
218 my $router = $self->addr_block->router
219 or return 'Cannot assign address from unallocated block:'.$self->addr_block->blocknum;
220 if(grep { $_->routernum == $router->routernum} $self->allowed_routers) {
223 return 'Router '.$router->routernum.' cannot provide svcpart '.$self->svcpart;
232 Returns a NetAddr::IP object containing the IP address of this service. The netmask
239 return new NetAddr::IP ($self->ip_addr);
244 Returns the FS::addr_block record (i.e. the address block) for this broadband service.
251 return qsearchs('addr_block', { blocknum => $self->blocknum });
256 =item allowed_routers
258 Returns a list of allowed FS::router objects.
262 sub allowed_routers {
265 return map { $_->router } qsearch('part_svc_router', { svcpart => $self->svcpart });
270 I think there's one place in the code where we actually use sb_field_hashref.
271 That's a bug in itself.
273 The real problem with it is that we're still grappling with the question of how
274 tightly xfields should be integrated with real fields. There are a few
275 different directions we could go with it--we I<could> override several
276 functions in Record so that xfields behave almost exactly like real fields (can
277 be set with setfield(), appear in fields() and hash(), used as criteria in
282 FS::svc_Common, FS::Record, FS::addr_block, FS::sb_field,
283 FS::part_svc, schema.html from the base documentation.