summaryrefslogtreecommitdiff
path: root/FS/FS/svc_broadband.pm
diff options
context:
space:
mode:
Diffstat (limited to 'FS/FS/svc_broadband.pm')
-rwxr-xr-xFS/FS/svc_broadband.pm490
1 files changed, 0 insertions, 490 deletions
diff --git a/FS/FS/svc_broadband.pm b/FS/FS/svc_broadband.pm
deleted file mode 100755
index 5ffe0e4..0000000
--- a/FS/FS/svc_broadband.pm
+++ /dev/null
@@ -1,490 +0,0 @@
-package FS::svc_broadband;
-
-use strict;
-use vars qw(@ISA $conf);
-use FS::Record qw( qsearchs qsearch dbh );
-use FS::svc_Common;
-use FS::cust_svc;
-use FS::addr_block;
-use FS::part_svc_router;
-use NetAddr::IP;
-
-@ISA = qw( FS::svc_Common );
-
-$FS::UID::callback{'FS::svc_broadband'} = sub {
- $conf = new FS::Conf;
-};
-
-=head1 NAME
-
-FS::svc_broadband - Object methods for svc_broadband records
-
-=head1 SYNOPSIS
-
- use FS::svc_broadband;
-
- $record = new FS::svc_broadband \%hash;
- $record = new FS::svc_broadband { 'column' => 'value' };
-
- $error = $record->insert;
-
- $error = $new_record->replace($old_record);
-
- $error = $record->delete;
-
- $error = $record->check;
-
- $error = $record->suspend;
-
- $error = $record->unsuspend;
-
- $error = $record->cancel;
-
-=head1 DESCRIPTION
-
-An FS::svc_broadband object represents a 'broadband' Internet connection, such
-as a DSL, cable modem, or fixed wireless link. These services are assumed to
-have the following properties:
-
-FS::svc_broadband inherits from FS::svc_Common. The following fields are
-currently supported:
-
-=over 4
-
-=item svcnum - primary key
-
-=item blocknum - see FS::addr_block
-
-=item
-speed_up - maximum upload speed, in bits per second. If set to zero, upload
-speed will be unlimited. Exports that do traffic shaping should handle this
-correctly, and not blindly set the upload speed to zero and kill the customer's
-connection.
-
-=item
-speed_down - maximum download speed, as above
-
-=item ip_addr - the customer's IP address. If the customer needs more than one
-IP address, set this to the address of the customer's router. As a result, the
-customer's router will have the same address for both its internal and external
-interfaces thus saving address space. This has been found to work on most NAT
-routers available.
-
-=back
-
-=head1 METHODS
-
-=over 4
-
-=item new HASHREF
-
-Creates a new svc_broadband. To add the record to the database, see
-"insert".
-
-Note that this stores the hash reference, not a distinct copy of the hash it
-points to. You can ask the object for a copy with the I<hash> method.
-
-=cut
-
-sub table_info {
- {
- 'name' => 'Broadband',
- 'name_plural' => 'Broadband services',
- 'longname_plural' => 'Fixed (username-less) broadband services',
- 'display_weight' => 50,
- 'cancel_weight' => 70,
- 'fields' => {
- 'description' => 'Descriptive label for this particular device.',
- 'speed_down' => 'Maximum download speed for this service in Kbps. 0 denotes unlimited.',
- 'speed_up' => 'Maximum upload speed for this service in Kbps. 0 denotes unlimited.',
- 'ip_addr' => 'IP address. Leave blank for automatic assignment.',
- 'blocknum' => { 'label' => 'Address block',
- 'type' => 'select',
- 'select_table' => 'addr_block',
- 'select_key' => 'blocknum',
- 'select_label' => 'cidr',
- 'disable_inventory' => 1,
- },
- },
- };
-}
-
-sub table { 'svc_broadband'; }
-
-sub table_dupcheck_fields { ( 'mac_addr' ); }
-
-=item search HASHREF
-
-Class method which returns a qsearch hash expression to search for parameters
-specified in HASHREF.
-
-Parameters:
-
-=over 4
-
-=item unlinked - set to search for all unlinked services. Overrides all other options.
-
-=item agentnum
-
-=item custnum
-
-=item svcpart
-
-=item ip_addr
-
-=item pkgpart - arrayref
-
-=item routernum - arrayref
-
-=item order_by
-
-=back
-
-=cut
-
-sub search {
- my ($class, $params) = @_;
- my @where = ();
- my @from = (
- 'LEFT JOIN cust_svc USING ( svcnum )',
- 'LEFT JOIN part_svc USING ( svcpart )',
- 'LEFT JOIN cust_pkg USING ( pkgnum )',
- 'LEFT JOIN cust_main USING ( custnum )',
- );
-
- # based on FS::svc_acct::search, probably the most mature of the bunch
- #unlinked
- push @where, 'pkgnum IS NULL' if $params->{'unlinked'};
-
- #agentnum
- if ( $params->{'agentnum'} =~ /^(\d+)$/ and $1 ) {
- push @where, "agentnum = $1";
- }
- push @where, $FS::CurrentUser::CurrentUser->agentnums_sql(
- 'null_right' => 'View/link unlinked services',
- 'table' => 'cust_main'
- );
-
- #custnum
- if ( $params->{'custnum'} =~ /^(\d+)$/ and $1 ) {
- push @where, "custnum = $1";
- }
-
- #pkgpart, now properly untainted, can be arrayref
- for my $pkgpart ( $params->{'pkgpart'} ) {
- if ( ref $pkgpart ) {
- my $where = join(',', map { /^(\d+)$/ ? $1 : () } @$pkgpart );
- push @where, "cust_pkg.pkgpart IN ($where)" if $where;
- }
- elsif ( $pkgpart =~ /^(\d+)$/ ) {
- push @where, "cust_pkg.pkgpart = $1";
- }
- }
-
- #routernum, can be arrayref
- for my $routernum ( $params->{'routernum'} ) {
- push @from, 'LEFT JOIN addr_block USING ( blocknum )';
- if ( ref $routernum and grep { $_ } @$routernum ) {
- my $where = join(',', map { /^(\d+)$/ ? $1 : () } @$routernum );
- push @where, "addr_block.routernum IN ($where)" if $where;
- }
- elsif ( $routernum =~ /^(\d+)$/ ) {
- push @where, "addr_block.routernum = $1";
- }
- }
-
- #svcnum
- if ( $params->{'svcnum'} =~ /^(\d+)$/ ) {
- push @where, "svcnum = $1";
- }
-
- #svcpart
- if ( $params->{'svcpart'} =~ /^(\d+)$/ ) {
- push @where, "svcpart = $1";
- }
-
- #ip_addr
- if ( $params->{'ip_addr'} =~ /^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$/ ) {
- push @where, "ip_addr = '$1'";
- }
-
- #custnum
- if ( $params->{'custnum'} =~ /^(\d+)$/ and $1) {
- push @where, "custnum = $1";
- }
-
- my $addl_from = join(' ', @from);
- my $extra_sql = '';
- $extra_sql = 'WHERE '.join(' AND ', @where) if @where;
- my $count_query = "SELECT COUNT(*) FROM svc_broadband $addl_from $extra_sql";
- return( {
- 'table' => 'svc_broadband',
- 'hashref' => {},
- 'select' => join(', ',
- 'svc_broadband.*',
- 'part_svc.svc',
- 'cust_main.custnum',
- FS::UI::Web::cust_sql_fields($params->{'cust_fields'}),
- ),
- 'extra_sql' => $extra_sql,
- 'addl_from' => $addl_from,
- 'order_by' => "ORDER BY ".($params->{'order_by'} || 'svcnum'),
- 'count_query' => $count_query,
- } );
-}
-
-=item search_sql STRING
-
-Class method which returns an SQL fragment to search for the given string.
-
-=cut
-
-sub search_sql {
- my( $class, $string ) = @_;
- if ( $string =~ /^(\d{1,3}\.){3}\d{1,3}$/ ) {
- $class->search_sql_field('ip_addr', $string );
- }elsif ( $string =~ /^([a-fA-F0-9]{12})$/ ) {
- $class->search_sql_field('mac_addr', uc($string));
- }elsif ( $string =~ /^(([a-fA-F0-9]{1,2}:){5}([a-fA-F0-9]{1,2}))$/ ) {
- $class->search_sql_field('mac_addr', uc("$2$3$4$5$6$7") );
- } else {
- '1 = 0'; #false
- }
-}
-
-=item label
-
-Returns the IP address.
-
-=cut
-
-sub label {
- my $self = shift;
- $self->ip_addr;
-}
-
-=item insert [ , OPTION => VALUE ... ]
-
-Adds this record to the database. If there is an error, returns the error,
-otherwise returns false.
-
-The additional fields pkgnum and svcpart (see FS::cust_svc) should be
-defined. An FS::cust_svc record will be created and inserted.
-
-Currently available options are: I<depend_jobnum>
-
-If I<depend_jobnum> is set (to a scalar jobnum or an array reference of
-jobnums), all provisioning jobs will have a dependancy on the supplied
-jobnum(s) (they will not run until the specific job(s) complete(s)).
-
-=cut
-
-# Standard FS::svc_Common::insert
-
-=item delete
-
-Delete this record from the database.
-
-=cut
-
-# Standard FS::svc_Common::delete
-
-=item replace OLD_RECORD
-
-Replaces the OLD_RECORD with this one in the database. If there is an error,
-returns the error, otherwise returns false.
-
-=cut
-
-# Standard FS::svc_Common::replace
-
-=item suspend
-
-Called by the suspend method of FS::cust_pkg (see FS::cust_pkg).
-
-=item unsuspend
-
-Called by the unsuspend method of FS::cust_pkg (see FS::cust_pkg).
-
-=item cancel
-
-Called by the cancel method of FS::cust_pkg (see FS::cust_pkg).
-
-=item check
-
-Checks all fields to make sure this is a valid broadband service. If there is
-an error, returns the error, otherwise returns false. Called by the insert
-and replace methods.
-
-=cut
-
-sub check {
- my $self = shift;
- my $x = $self->setfixed;
-
- return $x unless ref($x);
-
- my $error =
- $self->ut_numbern('svcnum')
- || $self->ut_numbern('blocknum')
- || $self->ut_textn('description')
- || $self->ut_number('speed_up')
- || $self->ut_number('speed_down')
- || $self->ut_ipn('ip_addr')
- || $self->ut_hexn('mac_addr')
- || $self->ut_hexn('auth_key')
- || $self->ut_coordn('latitude', -90, 90)
- || $self->ut_coordn('longitude', -180, 180)
- || $self->ut_sfloatn('altitude')
- || $self->ut_textn('vlan_profile')
- ;
- return $error if $error;
-
- if($self->speed_up < 0) { return 'speed_up must be positive'; }
- if($self->speed_down < 0) { return 'speed_down must be positive'; }
-
- my $cust_svc = $self->svcnum
- ? qsearchs('cust_svc', { 'svcnum' => $self->svcnum } )
- : '';
- my $cust_pkg;
- if ($cust_svc) {
- $cust_pkg = $cust_svc->cust_pkg;
- }else{
- $cust_pkg = qsearchs('cust_pkg', { 'pkgnum' => $self->pkgnum } );
- return "Invalid pkgnum" unless $cust_pkg;
- }
-
- if ($self->blocknum) {
- $error = $self->ut_foreign_key('blocknum', 'addr_block', 'blocknum');
- return $error if $error;
- }
-
- if ($cust_pkg && $self->blocknum) {
- my $addr_agentnum = $self->addr_block->agentnum;
- if ($addr_agentnum && $addr_agentnum != $cust_pkg->cust_main->agentnum) {
- return "Address block does not service this customer";
- }
- }
-
- $error = $self->_check_ip_addr;
- return $error if $error;
-
- $self->SUPER::check;
-}
-
-sub _check_ip_addr {
- my $self = shift;
-
- if (not($self->ip_addr) or $self->ip_addr eq '0.0.0.0') {
-
- return '' if $conf->exists('svc_broadband-allow_null_ip_addr'); #&& !$self->blocknum
-
- return "Must supply either address or block"
- unless $self->blocknum;
- my $next_addr = $self->addr_block->next_free_addr;
- if ($next_addr) {
- $self->ip_addr($next_addr->addr);
- } else {
- return "No free addresses in addr_block (blocknum: ".$self->blocknum.")";
- }
-
- }
-
- if (not($self->blocknum)) {
- return "Must supply either address or block"
- unless ($self->ip_addr and $self->ip_addr ne '0.0.0.0');
- my @block = grep { $_->NetAddr->contains($self->NetAddr) }
- map { $_->addr_block }
- $self->allowed_routers;
- if (scalar(@block)) {
- $self->blocknum($block[0]->blocknum);
- }else{
- return "Address not with available block.";
- }
- }
-
- # This should catch errors in the ip_addr. If it doesn't,
- # they'll almost certainly not map into the block anyway.
- my $self_addr = $self->NetAddr; #netmask is /32
- return ('Cannot parse address: ' . $self->ip_addr) unless $self_addr;
-
- my $block_addr = $self->addr_block->NetAddr;
- unless ($block_addr->contains($self_addr)) {
- return 'blocknum '.$self->blocknum.' does not contain address '.$self->ip_addr;
- }
-
- my $router = $self->addr_block->router
- or return 'Cannot assign address from unallocated block:'.$self->addr_block->blocknum;
- if(grep { $_->routernum == $router->routernum} $self->allowed_routers) {
- } # do nothing
- else {
- return 'Router '.$router->routernum.' cannot provide svcpart '.$self->svcpart;
- }
-
- '';
-}
-
-sub _check_duplicate {
- my $self = shift;
-
- return "MAC already in use"
- if ( $self->mac_addr &&
- scalar( qsearch( 'svc_broadband', { 'mac_addr', $self->mac_addr } ) )
- );
-
- '';
-}
-
-
-=item NetAddr
-
-Returns a NetAddr::IP object containing the IP address of this service. The netmask
-is /32.
-
-=cut
-
-sub NetAddr {
- my $self = shift;
- new NetAddr::IP ($self->ip_addr);
-}
-
-=item addr_block
-
-Returns the FS::addr_block record (i.e. the address block) for this broadband service.
-
-=cut
-
-sub addr_block {
- my $self = shift;
- qsearchs('addr_block', { blocknum => $self->blocknum });
-}
-
-=back
-
-=item allowed_routers
-
-Returns a list of allowed FS::router objects.
-
-=cut
-
-sub allowed_routers {
- my $self = shift;
- map { $_->router } qsearch('part_svc_router', { svcpart => $self->svcpart });
-}
-
-=head1 BUGS
-
-The business with sb_field has been 'fixed', in a manner of speaking.
-
-allowed_routers isn't agent virtualized because part_svc isn't agent
-virtualized
-
-=head1 SEE ALSO
-
-FS::svc_Common, FS::Record, FS::addr_block,
-FS::part_svc, schema.html from the base documentation.
-
-=cut
-
-1;
-